From c84ebb90b1f6c313e13869b3edf7201604d3df57 Mon Sep 17 00:00:00 2001 From: kmitresse Date: Fri, 8 Nov 2024 08:56:46 +0100 Subject: [PATCH] [Feat] - Toutes les notes de SSI sur la gestion d'un policyFile (sans policytool) et la signature avec et sans certification + fichier revision by lucas --- security/TPNote/Notes+Examples/CA/ca.crt | 20 ++ security/TPNote/Notes+Examples/CA/ca.key | 28 ++ .../Notes+Examples/Gerer_un_policytool.pdf | Bin 0 -> 41385 bytes ...ures_Numeriques_et_Certificats_en_Java.pdf | Bin 0 -> 60185 bytes .../TPNote/Notes+Examples/client/MANIFEST.MF | 1 + .../TPNote/Notes+Examples/client/Source.java | 5 + .../Notes+Examples/client/Source_Signed.jar | Bin 0 -> 3235 bytes .../Notes+Examples/client/certificat.cer | Bin 0 -> 819 bytes .../client/certificat_request.csr | 18 + .../client/certificat_signed.cer | 20 ++ .../TPNote/Notes+Examples/client/keystore.jks | Bin 0 -> 4572 bytes security/TPNote/Notes+Examples/policy | 9 + .../revision/revision/tp1/partie1/.policy | 3 + .../revision/revision/tp1/partie2/.policy | 4 + .../revision/tp1/partie2/GetProps.java | 28 ++ .../revision/revision/tp1/partie2/run.sh | 10 + .../revision/revision/tp1/partie3/Source.java | 5 + .../revision/revision/tp1/partie3/run.sh | 29 ++ .../revision/tp1/partie4/client/Source.java | 5 + .../revision/revision/tp1/partie4/run.sh | 112 ++++++ .../revision/tp1/partie5/client/.policy | 10 + .../revision/tp1/partie5/client/Source.java | 27 ++ .../revision/revision/tp1/partie5/run.sh | 114 ++++++ .../revision/revision/tp2/partie1/jaas.config | 5 + .../revision/revision/tp2/partie1/run.sh | 15 + .../tp2/partie1/sample/SampleAcn.java | 240 +++++++++++++ .../sample/module/SampleLoginModule.java | 337 ++++++++++++++++++ .../sample/principal/SamplePrincipal.java | 144 ++++++++ .../revision/revision/tp2/partie2/.policy | 7 + .../revision/tp2/partie2/SampleAcn.jar | Bin 0 -> 3266 bytes .../revision/tp2/partie2/SampleLM.jar | Bin 0 -> 3914 bytes .../revision/revision/tp2/partie2/jaas.config | 5 + .../revision/revision/tp2/partie2/run.sh | 28 ++ .../tp2/partie2/sample/SampleAcn.java | 237 ++++++++++++ .../sample/module/SampleLoginModule.java | 337 ++++++++++++++++++ .../sample/principal/SamplePrincipal.java | 141 ++++++++ .../revision/tp2/partie3/SampleAction.jar | Bin 0 -> 1196 bytes .../revision/tp2/partie3/SampleAzn.jar | Bin 0 -> 3745 bytes .../revision/tp2/partie3/SampleLM.jar | Bin 0 -> 3921 bytes .../revision/revision/tp2/partie3/azn.policy | 24 ++ .../revision/revision/tp2/partie3/foo.txt | 1 + .../revision/revision/tp2/partie3/jaas.config | 5 + .../revision/revision/tp2/partie3/run.sh | 31 ++ .../tp2/partie3/sample/SampleAction.java | 75 ++++ .../tp2/partie3/sample/SampleAzn.java | 265 ++++++++++++++ .../sample/module/SampleLoginModule.java | 337 ++++++++++++++++++ .../sample/principal/SamplePrincipal.java | 144 ++++++++ .../Notes+Examples/signatureAvecCertificat.sh | 112 ++++++ .../Notes+Examples/signatureSansCertificat.sh | 29 ++ 49 files changed, 2967 insertions(+) create mode 100644 security/TPNote/Notes+Examples/CA/ca.crt create mode 100644 security/TPNote/Notes+Examples/CA/ca.key create mode 100644 security/TPNote/Notes+Examples/Gerer_un_policytool.pdf create mode 100644 security/TPNote/Notes+Examples/Signatures_Numeriques_et_Certificats_en_Java.pdf create mode 100644 security/TPNote/Notes+Examples/client/MANIFEST.MF create mode 100755 security/TPNote/Notes+Examples/client/Source.java create mode 100644 security/TPNote/Notes+Examples/client/Source_Signed.jar create mode 100644 security/TPNote/Notes+Examples/client/certificat.cer create mode 100644 security/TPNote/Notes+Examples/client/certificat_request.csr create mode 100644 security/TPNote/Notes+Examples/client/certificat_signed.cer create mode 100644 security/TPNote/Notes+Examples/client/keystore.jks create mode 100644 security/TPNote/Notes+Examples/policy create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp1/partie1/.policy create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp1/partie2/.policy create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp1/partie2/GetProps.java create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp1/partie2/run.sh create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp1/partie3/Source.java create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp1/partie3/run.sh create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp1/partie4/client/Source.java create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp1/partie4/run.sh create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp1/partie5/client/.policy create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp1/partie5/client/Source.java create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp1/partie5/run.sh create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp2/partie1/jaas.config create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp2/partie1/run.sh create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp2/partie1/sample/SampleAcn.java create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp2/partie1/sample/module/SampleLoginModule.java create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp2/partie1/sample/principal/SamplePrincipal.java create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp2/partie2/.policy create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp2/partie2/SampleAcn.jar create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp2/partie2/SampleLM.jar create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp2/partie2/jaas.config create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp2/partie2/run.sh create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp2/partie2/sample/SampleAcn.java create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp2/partie2/sample/module/SampleLoginModule.java create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp2/partie2/sample/principal/SamplePrincipal.java create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp2/partie3/SampleAction.jar create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp2/partie3/SampleAzn.jar create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp2/partie3/SampleLM.jar create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp2/partie3/azn.policy create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp2/partie3/foo.txt create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp2/partie3/jaas.config create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp2/partie3/run.sh create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp2/partie3/sample/SampleAction.java create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp2/partie3/sample/SampleAzn.java create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp2/partie3/sample/module/SampleLoginModule.java create mode 100644 security/TPNote/Notes+Examples/revision/revision/tp2/partie3/sample/principal/SamplePrincipal.java create mode 100755 security/TPNote/Notes+Examples/signatureAvecCertificat.sh create mode 100755 security/TPNote/Notes+Examples/signatureSansCertificat.sh diff --git a/security/TPNote/Notes+Examples/CA/ca.crt b/security/TPNote/Notes+Examples/CA/ca.crt new file mode 100644 index 0000000..1b05c53 --- /dev/null +++ b/security/TPNote/Notes+Examples/CA/ca.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDRTCCAi2gAwIBAgIUeFkqQDxs67AqhUPln8Yzm44H2zkwDQYJKoZIhvcNAQEL +BQAwMjEUMBIGA1UEAwwLU2ltdWxhdGVkQ0ExDTALBgNVBAoMBE15Q0ExCzAJBgNV +BAYTAkZSMB4XDTI0MTEwNzIxMzk1NloXDTI1MTEwNzIxMzk1NlowMjEUMBIGA1UE +AwwLU2ltdWxhdGVkQ0ExDTALBgNVBAoMBE15Q0ExCzAJBgNVBAYTAkZSMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2kK6igwUFT7qLOwhrVva+yir/OF+ +p56T7kyXrp7UZwtIta7O5VT3BhhC8C1jVbK9hpTJ7FoSesksF+xwdapLiXBEj/B2 +COvNBFf432iGx+6fCAhkA95D8/zIxBf+QgbL5EgWPXn/emsZMomPH6wmwI20HTvL +ANbqfLe4vvU3KR+GcnfC24rQsoXgfZIHBKaa3Vrc005J+JhoCTY4NK3AAy/ngMm9 +dsmVgaPrBzzm6XYliqp8ma7xZTTjRIIKyow4aPVG1BQZW3Tayx30+8L6HR3niCDr +5MlNIP94hCC14i47UPRdOQQX4etSd8C9LbWHUkiSkf5Dmj84qqY3DihifQIDAQAB +o1MwUTAdBgNVHQ4EFgQU7uGkETin7lsxsjUOS3Udk6qZV60wHwYDVR0jBBgwFoAU +7uGkETin7lsxsjUOS3Udk6qZV60wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0B +AQsFAAOCAQEACfi9sjsMMNWPTlvF8ycvVQ0Kn8yhx6deQL5NYSPc48BD0miaPhvL +jaumUzbzNxkI0XiyKBpXKOLjLt3zyBQh2tpBW5oqJ5q0L6oiOtswvZpXklyYN2RR +RX3M0WFDcQD7uRxSXznKzwkFqxbY+kNMWEfYtIzCEFJ8BYkKBSTR8S6MYbCSlheK +PbW+U3+1LMcYuERMfSywD2C+nzb9Xz1LSZCVkaltEknvMj/tzUcytxxjRs2RqSsr +phyTjAE2HxpN/buQ9WmIrUbBBRrRKAVl+Vv1JB5A8R/gzeNe3nbv1zkGak0M2ddn +Dy4VDMgwwSee/X8F/tG29R9hEI//d2kR3w== +-----END CERTIFICATE----- diff --git a/security/TPNote/Notes+Examples/CA/ca.key b/security/TPNote/Notes+Examples/CA/ca.key new file mode 100644 index 0000000..3cb1090 --- /dev/null +++ b/security/TPNote/Notes+Examples/CA/ca.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDaQrqKDBQVPuos +7CGtW9r7KKv84X6nnpPuTJeuntRnC0i1rs7lVPcGGELwLWNVsr2GlMnsWhJ6ySwX +7HB1qkuJcESP8HYI680EV/jfaIbH7p8ICGQD3kPz/MjEF/5CBsvkSBY9ef96axky +iY8frCbAjbQdO8sA1up8t7i+9TcpH4Zyd8LbitCyheB9kgcEpprdWtzTTkn4mGgJ +Njg0rcADL+eAyb12yZWBo+sHPObpdiWKqnyZrvFlNONEggrKjDho9UbUFBlbdNrL +HfT7wvodHeeIIOvkyU0g/3iEILXiLjtQ9F05BBfh61J3wL0ttYdSSJKR/kOaPziq +pjcOKGJ9AgMBAAECggEABsISrxQVKhw+2YG9QDYsJ2M4whWEW7HSEEqgVriVyJQF +nhSJ1PmGxZJKPlAVd5GXgzuHrhES6ejhO+NnDwmlGZ4XjWJrcTbF7BjCPL6qj7XA +iFnkKOeAsKUW3VWF2qsFtK2TvLcSlUqMJu+x9g/ZSlSI62/OxxmgfJieuJD0son3 +9ln6+95UZfpmlOSFb5G1+oDAX1b+S2ykdSG8Daqibh6egFn9WZ9CLmhVhkwnWPli +r+EXZdYHxulU+454lz1jUT3ooWehp1Lkurlysr4Q3B52Zwsdg9pum8kCewLlz3la +agGYdXoW9sW3AWN+J3+n5oOsXr3/aZ+CV8GobRgbwQKBgQDnwLYiOOrEFaLxMR0/ +CrW9smoL6IMRPRt7CpG6ePvKoaEaJMfBfutgUmbh2vp6KMAilkaZ7sBPxSY5Td+p +Cv4IxJ/dplMqknnujhC3vQJkdrrown//4PuNGKq7P0q/CY2KTTTj1liM0JorhPr5 +8ycUj7gxclj72PyqJfeBJKRvQQKBgQDxGKSZ35z000jcRnt9L8JOhcZZX7GAJX9m +ktGhmu8pvCGBUryKwva8+Ct6MO+uLfadNXN2T0okfKAiTDx+O5GFobgMcmFk/3ki +WBbub/Nxk+1qgfG3gb6dyRzJoSIvMMoVnAQLNiGZp+xp9IHixMBrGy21kEFwzZn8 +hgHKymHgPQKBgDagnk4CzJPb5cSkpxgtFhnY7FZSQFLX7JpcK22hBvkEkEzxToS1 +vhW+VrH2RAR3hpKgiZPPS1WCSzhGuunFxYubjXNZuVDXphYtNpOY4e98bSJgdnuC +NMlVfykUCjJttgdbm5P4+nZ21WBcwCwavKOEHQ7KvV7gDu6sdGLkmD4BAoGAULz6 +6li7HDXhUXr9AchLnrYn3WgxbgOgrX3/W8ohy20oH0HQx/tQW6oUDUB0E3Vq/+yV +dQpKfvuJONMk8vUJ36FvnCN1wDfZngm37DNraB6sxB0uEFEPv5FI5bDjXMBO/HuZ +0xNWnzlf73+lO4a+FWAtp37em2MO7UUHNp0dt9UCgYBTbDhzIV7aDluEUqJbBa2Y +CBvkJ/9+utAL9eyf30y+Hh3ZWKxc5kuRK6xlJyxamZmFqpaGLsmN+KaWEgUojrXv +j7Es/ry5W6mDiIIbCSULu1e/7cdUsno/HhdSxVyWKAuOjFtLEWC4pXGiD6Vpgpoo +wVO01w/kd7bhhkAqskuGxQ== +-----END PRIVATE KEY----- diff --git a/security/TPNote/Notes+Examples/Gerer_un_policytool.pdf b/security/TPNote/Notes+Examples/Gerer_un_policytool.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1a32f56b4b254b1fc658585c7531981f60cf4966 GIT binary patch literal 41385 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
    Cc;r!@9f`YDyrIJ0L=RRq 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�OuVt%@894G`;e0~nd~%Cym?89E^_f~F1h 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 literal 0 HcmV?d00001 diff --git a/security/TPNote/Notes+Examples/policy b/security/TPNote/Notes+Examples/policy new file mode 100644 index 0000000..27e3953 --- /dev/null +++ b/security/TPNote/Notes+Examples/policy @@ -0,0 +1,9 @@ +keystore "./client/keystore.jks" + +grant signedBy "KeyAlias" { + permission java.io.FilePermission "${user.home}${/}PauUniversty/Master-TI-2/security/Notes/Example/Client/Source_Signed.jar", "read, execute"; +}; + +grant codeBase "file:/home/kmitresse/PauUniversity/Master-TI-2/security/Notes/" { + permission java.util.PropertyPermission "user.home", "read"; +}; \ No newline at end of file diff --git a/security/TPNote/Notes+Examples/revision/revision/tp1/partie1/.policy b/security/TPNote/Notes+Examples/revision/revision/tp1/partie1/.policy new file mode 100644 index 0000000..f8040b0 --- /dev/null +++ b/security/TPNote/Notes+Examples/revision/revision/tp1/partie1/.policy @@ -0,0 +1,3 @@ +grant codeBase "file:./" { + +}; \ No newline at end of file diff --git a/security/TPNote/Notes+Examples/revision/revision/tp1/partie2/.policy b/security/TPNote/Notes+Examples/revision/revision/tp1/partie2/.policy new file mode 100644 index 0000000..4a06042 --- /dev/null +++ b/security/TPNote/Notes+Examples/revision/revision/tp1/partie2/.policy @@ -0,0 +1,4 @@ +grant codeBase "file:${user.home}${/}Documents${/}Github${/}SecuriteSystemesInfo${/}revision${/}tp1${/}partie2${/}" { + permission "java.util.PropertyPermission" "user.home", "read"; + permission "java.util.PropertyPermission" "java.home", "read"; +}; \ No newline at end of file diff --git a/security/TPNote/Notes+Examples/revision/revision/tp1/partie2/GetProps.java b/security/TPNote/Notes+Examples/revision/revision/tp1/partie2/GetProps.java new file mode 100644 index 0000000..643f4b7 --- /dev/null +++ b/security/TPNote/Notes+Examples/revision/revision/tp1/partie2/GetProps.java @@ -0,0 +1,28 @@ +import java.lang.*; + +class GetProps { + + public static void main(String[] args) { + + try { + final String OS_NAME = GetProps.getProperty("os.name"); + final String JAVA_VERSION = GetProps.getProperty("java.version"); + final String USER_HOME = GetProps.getProperty("user.home"); + final String JAVA_HOME = GetProps.getProperty("java.home"); + + System.out.println( + "os.name : " + OS_NAME + "\n" + + "java.version : " + JAVA_VERSION + "\n" + + "user.home : " + USER_HOME + "\n" + + "java.home : " + JAVA_HOME + ); + } catch (Exception e) { + System.err.println("Caught exception " + e.toString()); + } + } + + private static String getProperty(String property_name) { + final String DEFAULT_VALUE = "not specified"; + return System.getProperty(property_name, DEFAULT_VALUE); + } +} \ No newline at end of file diff --git a/security/TPNote/Notes+Examples/revision/revision/tp1/partie2/run.sh b/security/TPNote/Notes+Examples/revision/revision/tp1/partie2/run.sh new file mode 100644 index 0000000..aa55edd --- /dev/null +++ b/security/TPNote/Notes+Examples/revision/revision/tp1/partie2/run.sh @@ -0,0 +1,10 @@ +# Compile Java file +javac ./GetProps.java + +# Execute with security manager and policy file +java -Djava.security.manager \ + -Djava.security.policy=.policy \ + GetProps + +# Remove compiled file +rm ./GetProps.class \ No newline at end of file diff --git a/security/TPNote/Notes+Examples/revision/revision/tp1/partie3/Source.java b/security/TPNote/Notes+Examples/revision/revision/tp1/partie3/Source.java new file mode 100644 index 0000000..72fa90f --- /dev/null +++ b/security/TPNote/Notes+Examples/revision/revision/tp1/partie3/Source.java @@ -0,0 +1,5 @@ +public class Source { + public static void main(String[] args) { + System.out.println("Hello world!"); + } +} diff --git a/security/TPNote/Notes+Examples/revision/revision/tp1/partie3/run.sh b/security/TPNote/Notes+Examples/revision/revision/tp1/partie3/run.sh new file mode 100644 index 0000000..8519535 --- /dev/null +++ b/security/TPNote/Notes+Examples/revision/revision/tp1/partie3/run.sh @@ -0,0 +1,29 @@ +# Reset +rm ./keystore.jks ./Source_Signed.jar + +# Génère un keystore +keytool -genkeypair \ + -alias SourceKeyAlias \ + -keyalg RSA \ + -keysize 2048 \ + -keystore keystore.jks \ + -validity 365 + +# Compilation +javac ./Source.java + +# Créer un fichier MANIFEST.MF avec l'attribut Main-Class +echo "Main-Class: Source" > MANIFEST.MF + +# Crée le fichier JAR non signé avec le MANIFEST.MF modifié +jar cmf MANIFEST.MF Source.jar Source.class + +# Convertir en fichier JAR signé +jarsigner -keystore keystore.jks \ + -signedjar Source_Signed.jar Source.jar SourceKeyAlias + +# Supprime les artéfacts +rm ./Source.class ./Source.jar MANIFEST.MF + +# Essaye d'exécuter ton fichier JAR signé +java -jar Source_Signed.jar diff --git a/security/TPNote/Notes+Examples/revision/revision/tp1/partie4/client/Source.java b/security/TPNote/Notes+Examples/revision/revision/tp1/partie4/client/Source.java new file mode 100644 index 0000000..72fa90f --- /dev/null +++ b/security/TPNote/Notes+Examples/revision/revision/tp1/partie4/client/Source.java @@ -0,0 +1,5 @@ +public class Source { + public static void main(String[] args) { + System.out.println("Hello world!"); + } +} diff --git a/security/TPNote/Notes+Examples/revision/revision/tp1/partie4/run.sh b/security/TPNote/Notes+Examples/revision/revision/tp1/partie4/run.sh new file mode 100644 index 0000000..ca5b9ab --- /dev/null +++ b/security/TPNote/Notes+Examples/revision/revision/tp1/partie4/run.sh @@ -0,0 +1,112 @@ +#!/bin/bash + +# Reset +rm -rf ./CA +rm ./client/certificat_request.csr \ + ./client/certificat_signed.cer \ + ./client/certificat.cer \ + ./client/keystore.jks \ + ./client/Source_Signed.jar + +########################################## + +# Création des dossiers CA et client s'ils n'existent pas déjà +mkdir -p CA client + +# Génération de la clé privée de la CA +openssl genrsa -out CA/ca.key 2048 +echo "[CA] - génération de la clé privée : OK" + +# Génération du certificat auto-signé de la CA +openssl req -x509 -new -nodes \ + -key CA/ca.key -sha256 -days 365 \ + -out CA/ca.crt \ + -subj "/CN=SimulatedCA/O=MyCA/C=FR" +echo "[CA] - génération du certificat auto-signé : OK" + +# Génération du keystore du client +keytool -genkeypair \ + -alias KeyAlias \ + -keyalg RSA \ + -keysize 2048 \ + -keystore client/keystore.jks \ + -validity 365 \ + -dname "CN=ClientName, OU=ClientUnit, O=ClientOrg, L=ClientCity, S=ClientState, C=FR" \ + -storepass changeit \ + -keypass changeit +echo "[Client] - Génération du keystore : OK" + +# Génération de la demande de certificat (CSR) pour le client +keytool -certreq \ + -alias KeyAlias \ + -keystore client/keystore.jks \ + -file client/certificat_request.csr \ + -storepass changeit +echo "[Client] - Génération de la demande de certification : OK" + +# La CA signe la demande de certificat du client +openssl x509 -req \ + -in client/certificat_request.csr \ + -CA CA/ca.crt -CAkey CA/ca.key -CAcreateserial \ + -out client/certificat_signed.cer -days 365 -sha256 +echo "[CA] - Signature de la demande de certificat : OK" + +# Importation du certificat de la CA dans le keystore du client +keytool -import \ + -trustcacerts \ + -alias SimulatedCA \ + -file CA/ca.crt \ + -keystore client/keystore.jks \ + -noprompt \ + -storepass changeit +echo "[Client] - Import du certificat du CA : OK" + +# Importation du certificat signé dans le keystore du client +keytool -import \ + -alias KeyAlias \ + -keystore client/keystore.jks \ + -file client/certificat_signed.cer \ + -noprompt \ + -storepass changeit +echo "[Client] - Import du certificat signé : OK" + +# Exportation du certificat signé pour distribution +keytool -export \ + -alias KeyAlias \ + -keystore client/keystore.jks \ + -file client/certificat.cer \ + -storepass changeit +echo "[Client] - Export du certificat signé : OK" + +########################################## + +cd ./client/ + +# Compile notre fichier java +javac ./Source.java +echo "[Client] - Compilation du .java : OK" + +# Créer un fichier MANIFEST.MF avec l'attribut Main-Class +echo "Main-Class: Source" > ./MANIFEST.MF + +# Créé le fichier Jar non signé +jar cmf ./MANIFEST.MF ./Source.jar ./Source.class +echo "[Client] - Creation du fichier .jar : OK" + +# Convertis en fichier jar signé +jarsigner -keystore ./keystore.jks \ + -storepass changeit \ + -signedjar ./Source_Signed.jar ./Source.jar KeyAlias +echo "[Client] - Creation du fichier .jar signé : OK" + +# Supprime les artéfacts +rm ./Source.class ./Source.jar ./MANIFEST.MF + +# On peut vérifier que notre certificat est bien valide +jarsigner -verify ./Source_Signed.jar +echo "[Client] - Vérification du certificat : OK" + +cd .. + +# Executer le jar signé +java -jar ./client/Source_Signed.jar diff --git a/security/TPNote/Notes+Examples/revision/revision/tp1/partie5/client/.policy b/security/TPNote/Notes+Examples/revision/revision/tp1/partie5/client/.policy new file mode 100644 index 0000000..a378577 --- /dev/null +++ b/security/TPNote/Notes+Examples/revision/revision/tp1/partie5/client/.policy @@ -0,0 +1,10 @@ +keystore "keystore.jks"; + +grant signedBy "KeyAlias" { + permission java.io.FilePermission "${user.home}${/}Documents${/}Github${/}SecuriteSystemesInfo${/}revision${/}tp1${/}partie5${/}client${/}Source_Signed.jar", "read, execute"; +}; + +grant codeBase "file:${user.home}${/}Documents${/}Github${/}SecuriteSystemesInfo${/}revision${/}tp1${/}partie5${/}client${/}Source_Signed.jar" { + permission "java.util.PropertyPermission" "user.home", "read"; + permission "java.util.PropertyPermission" "java.home", "read"; +}; \ No newline at end of file diff --git a/security/TPNote/Notes+Examples/revision/revision/tp1/partie5/client/Source.java b/security/TPNote/Notes+Examples/revision/revision/tp1/partie5/client/Source.java new file mode 100644 index 0000000..3d62112 --- /dev/null +++ b/security/TPNote/Notes+Examples/revision/revision/tp1/partie5/client/Source.java @@ -0,0 +1,27 @@ +import java.lang.*; + +public class Source { + public static void main(String[] args) { + + try { + final String OS_NAME = Source.getProperty("os.name"); + final String JAVA_VERSION = Source.getProperty("java.version"); + final String USER_HOME = Source.getProperty("user.home"); + final String JAVA_HOME = Source.getProperty("java.home"); + + System.out.println( + "os.name : " + OS_NAME + "\n" + + "java.version : " + JAVA_VERSION + "\n" + + "user.home : " + USER_HOME + "\n" + + "java.home : " + JAVA_HOME + ); + } catch (Exception e) { + System.err.println("Caught exception " + e.toString()); + } +} + + private static String getProperty(String property_name) { + final String DEFAULT_VALUE = "not specified"; + return System.getProperty(property_name, DEFAULT_VALUE); + } +} \ No newline at end of file diff --git a/security/TPNote/Notes+Examples/revision/revision/tp1/partie5/run.sh b/security/TPNote/Notes+Examples/revision/revision/tp1/partie5/run.sh new file mode 100644 index 0000000..5a1b267 --- /dev/null +++ b/security/TPNote/Notes+Examples/revision/revision/tp1/partie5/run.sh @@ -0,0 +1,114 @@ +#!/bin/bash + +# Reset +rm -rf ./CA +rm ./client/certificat_request.csr \ + ./client/certificat_signed.cer \ + ./client/certificat.cer \ + ./client/keystore.jks \ + ./client/Source_Signed.jar + +########################################## + +# Création des dossiers CA et client s'ils n'existent pas déjà +mkdir -p CA client + +# Génération de la clé privée de la CA +openssl genrsa -out CA/ca.key 2048 +echo "[CA] - génération de la clé privée : OK" + +# Génération du certificat auto-signé de la CA +openssl req -x509 -new -nodes \ + -key CA/ca.key -sha256 -days 365 \ + -out CA/ca.crt \ + -subj "/CN=SimulatedCA/O=MyCA/C=FR" +echo "[CA] - génération du certificat auto-signé : OK" + +# Génération du keystore du client +keytool -genkeypair \ + -alias KeyAlias \ + -keyalg RSA \ + -keysize 2048 \ + -keystore client/keystore.jks \ + -validity 365 \ + -dname "CN=ClientName, OU=ClientUnit, O=ClientOrg, L=ClientCity, S=ClientState, C=FR" \ + -storepass changeit \ + -keypass changeit +echo "[Client] - Génération du keystore : OK" + +# Génération de la demande de certificat (CSR) pour le client +keytool -certreq \ + -alias KeyAlias \ + -keystore client/keystore.jks \ + -file client/certificat_request.csr \ + -storepass changeit +echo "[Client] - Génération de la demande de certification : OK" + +# La CA signe la demande de certificat du client +openssl x509 -req \ + -in client/certificat_request.csr \ + -CA CA/ca.crt -CAkey CA/ca.key -CAcreateserial \ + -out client/certificat_signed.cer -days 365 -sha256 +echo "[CA] - Signature de la demande de certificat : OK" + +# Importation du certificat de la CA dans le keystore du client +keytool -import \ + -trustcacerts \ + -alias SimulatedCA \ + -file CA/ca.crt \ + -keystore client/keystore.jks \ + -noprompt \ + -storepass changeit +echo "[Client] - Import du certificat du CA : OK" + +# Importation du certificat signé dans le keystore du client +keytool -import \ + -alias KeyAlias \ + -keystore client/keystore.jks \ + -file client/certificat_signed.cer \ + -noprompt \ + -storepass changeit +echo "[Client] - Import du certificat signé : OK" + +# Exportation du certificat signé pour distribution +keytool -export \ + -alias KeyAlias \ + -keystore client/keystore.jks \ + -file client/certificat.cer \ + -storepass changeit +echo "[Client] - Export du certificat signé : OK" + +########################################## + +cd client + +# Compile notre fichier java +javac Source.java +echo "[Client] - Compilation du .java : OK" + +# Créer un fichier MANIFEST.MF avec l'attribut Main-Class +echo "Main-Class: Source" > MANIFEST.MF + +# Créé le fichier Jar non signé +jar cmf MANIFEST.MF Source.jar Source.class +echo "[Client] - Creation du fichier .jar : OK" + +# Convertis en fichier jar signé +jarsigner -keystore keystore.jks \ + -storepass changeit \ + -signedjar Source_Signed.jar Source.jar KeyAlias +echo "[Client] - Creation du fichier .jar signé : OK" + +# Supprime les artéfacts +rm Source.class Source.jar MANIFEST.MF + +# On peut vérifier que notre certificat est bien valide +jarsigner -verify Source_Signed.jar +echo "[Client] - Vérification du certificat : OK" + +# Executer le jar signé +java -Djava.security.manager \ + -Djava.security.policy=.policy \ + -jar Source_Signed.jar + +cd .. \ No newline at end of file diff --git a/security/TPNote/Notes+Examples/revision/revision/tp2/partie1/jaas.config b/security/TPNote/Notes+Examples/revision/revision/tp2/partie1/jaas.config new file mode 100644 index 0000000..deda887 --- /dev/null +++ b/security/TPNote/Notes+Examples/revision/revision/tp2/partie1/jaas.config @@ -0,0 +1,5 @@ +/** Login Configuration for the JAAS Sample Application **/ + +Sample { + sample.module.SampleLoginModule required debug=true; +}; \ No newline at end of file diff --git a/security/TPNote/Notes+Examples/revision/revision/tp2/partie1/run.sh b/security/TPNote/Notes+Examples/revision/revision/tp2/partie1/run.sh new file mode 100644 index 0000000..b57d526 --- /dev/null +++ b/security/TPNote/Notes+Examples/revision/revision/tp2/partie1/run.sh @@ -0,0 +1,15 @@ +# Compile Java files +javac \ + sample/SampleAcn.java \ + sample/module/SampleLoginModule.java \ + sample/principal/SamplePrincipal.java + +# Execute +java -Djava.security.auth.login.config==jaas.config sample.SampleAcn + +# Reset +rm \ + ./sample/MyCallbackHandler.class \ + ./sample/SampleAcn.class \ + ./sample/module/SampleLoginModule.class \ + ./sample/principal/SamplePrincipal.class \ No newline at end of file diff --git a/security/TPNote/Notes+Examples/revision/revision/tp2/partie1/sample/SampleAcn.java b/security/TPNote/Notes+Examples/revision/revision/tp2/partie1/sample/SampleAcn.java new file mode 100644 index 0000000..260a7bc --- /dev/null +++ b/security/TPNote/Notes+Examples/revision/revision/tp2/partie1/sample/SampleAcn.java @@ -0,0 +1,240 @@ +/* + * + * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * -Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * -Redistribution in binary form must reproduct the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Oracle nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any + * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY + * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY + * DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT OF OR + * RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR + * ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE + * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, + * SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER + * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF + * THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that Software is not designed, licensed or + * intended for use in the design, construction, operation or + * maintenance of any nuclear facility. + */ + +package sample; + +import java.io.*; +import java.util.*; +import javax.security.auth.login.*; +import javax.security.auth.*; +import javax.security.auth.callback.*; + +/** + *

    This Sample application attempts to authenticate a user + * and reports whether or not the authentication was successful. + */ +public class SampleAcn { + + /** + * Attempt to authenticate the user. + * + *

    + * + * @param args input arguments for this application. These are ignored. + */ + public static void main(String[] args) { + + // Obtain a LoginContext, needed for authentication. Tell it + // to use the LoginModule implementation specified by the + // entry named "Sample" in the JAAS login configuration + // file and to also use the specified CallbackHandler. + LoginContext lc = null; + try { + lc = new LoginContext("Sample", new MyCallbackHandler()); + } catch (LoginException le) { + System.err.println("Cannot create LoginContext. " + + le.getMessage()); + System.exit(-1); + } catch (SecurityException se) { + System.err.println("Cannot create LoginContext. " + + se.getMessage()); + System.exit(-1); + } + + // the user has 3 attempts to authenticate successfully + int i; + for (i = 0; i < 3; i++) { + try { + + // attempt authentication + lc.login(); + + // if we return with no exception, authentication succeeded + break; + + } catch (LoginException le) { + + System.err.println("Authentication failed:"); + System.err.println(" " + le.getMessage()); + try { + Thread.currentThread().sleep(3000); + } catch (Exception e) { + // ignore + } + + } + } + + // did they fail three times? + if (i == 3) { + System.out.println("Sorry"); + System.exit(-1); + } + + System.out.println("Authentication succeeded!"); + + } +} + + +/** + * The application implements the CallbackHandler. + * + *

    This application is text-based. Therefore it displays information + * to the user using the OutputStreams System.out and System.err, + * and gathers input from the user using the InputStream System.in. + */ +class MyCallbackHandler implements CallbackHandler { + + /** + * Invoke an array of Callbacks. + * + *

    + * + * @param callbacks an array of Callback objects which contain + * the information requested by an underlying security + * service to be retrieved or displayed. + * + * @exception java.io.IOException if an input or output error occurs.

    + * + * @exception UnsupportedCallbackException if the implementation of this + * method does not support one or more of the Callbacks + * specified in the callbacks parameter. + */ + public void handle(Callback[] callbacks) + throws IOException, UnsupportedCallbackException { + + for (int i = 0; i < callbacks.length; i++) { + if (callbacks[i] instanceof TextOutputCallback) { + + // display the message according to the specified type + TextOutputCallback toc = (TextOutputCallback)callbacks[i]; + switch (toc.getMessageType()) { + case TextOutputCallback.INFORMATION: + System.out.println(toc.getMessage()); + break; + case TextOutputCallback.ERROR: + System.out.println("ERROR: " + toc.getMessage()); + break; + case TextOutputCallback.WARNING: + System.out.println("WARNING: " + toc.getMessage()); + break; + default: + throw new IOException("Unsupported message type: " + + toc.getMessageType()); + } + + } else if (callbacks[i] instanceof NameCallback) { + + // prompt the user for a username + NameCallback nc = (NameCallback)callbacks[i]; + + System.err.print(nc.getPrompt()); + System.err.flush(); + nc.setName((new BufferedReader + (new InputStreamReader(System.in))).readLine()); + + } else if (callbacks[i] instanceof PasswordCallback) { + + // prompt the user for sensitive information + PasswordCallback pc = (PasswordCallback)callbacks[i]; + System.err.print(pc.getPrompt()); + System.err.flush(); + pc.setPassword(readPassword(System.in)); + + } else { + throw new UnsupportedCallbackException + (callbacks[i], "Unrecognized Callback"); + } + } + } + + // Reads user password from given input stream. + private char[] readPassword(InputStream in) throws IOException { + + char[] lineBuffer; + char[] buf; + int i; + + buf = lineBuffer = new char[128]; + + int room = buf.length; + int offset = 0; + int c; + +loop: while (true) { + switch (c = in.read()) { + case -1: + case '\n': + break loop; + + case '\r': + int c2 = in.read(); + if ((c2 != '\n') && (c2 != -1)) { + if (!(in instanceof PushbackInputStream)) { + in = new PushbackInputStream(in); + } + ((PushbackInputStream)in).unread(c2); + } else + break loop; + + default: + if (--room < 0) { + buf = new char[offset + 128]; + room = buf.length - offset - 1; + System.arraycopy(lineBuffer, 0, buf, 0, offset); + Arrays.fill(lineBuffer, ' '); + lineBuffer = buf; + } + buf[offset++] = (char) c; + break; + } + } + + if (offset == 0) { + return null; + } + + char[] ret = new char[offset]; + System.arraycopy(buf, 0, ret, 0, offset); + Arrays.fill(buf, ' '); + + return ret; + } +} \ No newline at end of file diff --git a/security/TPNote/Notes+Examples/revision/revision/tp2/partie1/sample/module/SampleLoginModule.java b/security/TPNote/Notes+Examples/revision/revision/tp2/partie1/sample/module/SampleLoginModule.java new file mode 100644 index 0000000..0f4b88e --- /dev/null +++ b/security/TPNote/Notes+Examples/revision/revision/tp2/partie1/sample/module/SampleLoginModule.java @@ -0,0 +1,337 @@ +/* + * + * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * -Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * -Redistribution in binary form must reproduct the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Oracle nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any + * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY + * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY + * DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT OF OR + * RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR + * ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE + * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, + * SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER + * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF + * THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that Software is not designed, licensed or + * intended for use in the design, construction, operation or + * maintenance of any nuclear facility. + */ + +package sample.module; + +import java.util.*; +import java.io.IOException; +import javax.security.auth.*; +import javax.security.auth.callback.*; +import javax.security.auth.login.*; +import javax.security.auth.spi.*; +import sample.principal.SamplePrincipal; + +/** + *

    This sample LoginModule authenticates users with a password. + * + *

    This LoginModule only recognizes one user: testUser + *

    testUser's password is: testPassword + * + *

    If testUser successfully authenticates itself, + * a SamplePrincipal with the testUser's user name + * is added to the Subject. + * + *

    This LoginModule recognizes the debug option. + * If set to true in the login Configuration, + * debug messages will be output to the output stream, System.out. + * + */ +public class SampleLoginModule implements LoginModule { + + // initial state + private Subject subject; + private CallbackHandler callbackHandler; + private Map sharedState; + private Map options; + + // configurable option + private boolean debug = false; + + // the authentication status + private boolean succeeded = false; + private boolean commitSucceeded = false; + + // username and password + private String username; + private char[] password; + + // testUser's SamplePrincipal + private SamplePrincipal userPrincipal; + + /** + * Initialize this LoginModule. + * + *

    + * + * @param subject the Subject to be authenticated.

    + * + * @param callbackHandler a CallbackHandler for communicating + * with the end user (prompting for user names and + * passwords, for example).

    + * + * @param sharedState shared LoginModule state.

    + * + * @param options options specified in the login + * Configuration for this particular + * LoginModule. + */ + public void initialize(Subject subject, + CallbackHandler callbackHandler, + Map sharedState, + Map options) { + + this.subject = subject; + this.callbackHandler = callbackHandler; + this.sharedState = sharedState; + this.options = options; + + // initialize any configured options + debug = "true".equalsIgnoreCase((String)options.get("debug")); + } + + /** + * Authenticate the user by prompting for a user name and password. + * + *

    + * + * @return true in all cases since this LoginModule + * should not be ignored. + * + * @exception FailedLoginException if the authentication fails.

    + * + * @exception LoginException if this LoginModule + * is unable to perform the authentication. + */ + public boolean login() throws LoginException { + + // prompt for a user name and password + if (callbackHandler == null) + throw new LoginException("Error: no CallbackHandler available " + + "to garner authentication information from the user"); + + Callback[] callbacks = new Callback[2]; + callbacks[0] = new NameCallback("user name: "); + callbacks[1] = new PasswordCallback("password: ", false); + + try { + callbackHandler.handle(callbacks); + username = ((NameCallback)callbacks[0]).getName(); + char[] tmpPassword = ((PasswordCallback)callbacks[1]).getPassword(); + if (tmpPassword == null) { + // treat a NULL password as an empty password + tmpPassword = new char[0]; + } + password = new char[tmpPassword.length]; + System.arraycopy(tmpPassword, 0, + password, 0, tmpPassword.length); + ((PasswordCallback)callbacks[1]).clearPassword(); + + } catch (java.io.IOException ioe) { + throw new LoginException(ioe.toString()); + } catch (UnsupportedCallbackException uce) { + throw new LoginException("Error: " + uce.getCallback().toString() + + " not available to garner authentication information " + + "from the user"); + } + + // print debugging information + if (debug) { + System.out.println("\t\t[SampleLoginModule] " + + "user entered user name: " + + username); + System.out.print("\t\t[SampleLoginModule] " + + "user entered password: "); + for (int i = 0; i < password.length; i++) + System.out.print(password[i]); + System.out.println(); + } + + // verify the username/password + boolean usernameCorrect = false; + boolean passwordCorrect = false; + if (username.equals("testUser")) + usernameCorrect = true; + if (usernameCorrect && + password.length == 12 && + password[0] == 't' && + password[1] == 'e' && + password[2] == 's' && + password[3] == 't' && + password[4] == 'P' && + password[5] == 'a' && + password[6] == 's' && + password[7] == 's' && + password[8] == 'w' && + password[9] == 'o' && + password[10] == 'r' && + password[11] == 'd') { + + // authentication succeeded!!! + passwordCorrect = true; + if (debug) + System.out.println("\t\t[SampleLoginModule] " + + "authentication succeeded"); + succeeded = true; + return true; + } else { + + // authentication failed -- clean out state + if (debug) + System.out.println("\t\t[SampleLoginModule] " + + "authentication failed"); + succeeded = false; + username = null; + for (int i = 0; i < password.length; i++) + password[i] = ' '; + password = null; + if (!usernameCorrect) { + throw new FailedLoginException("User Name Incorrect"); + } else { + throw new FailedLoginException("Password Incorrect"); + } + } + } + + /** + *

    This method is called if the LoginContext's + * overall authentication succeeded + * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules + * succeeded). + * + *

    If this LoginModule's own authentication attempt + * succeeded (checked by retrieving the private state saved by the + * login method), then this method associates a + * SamplePrincipal + * with the Subject located in the + * LoginModule. If this LoginModule's own + * authentication attempted failed, then this method removes + * any state that was originally saved. + * + *

    + * + * @exception LoginException if the commit fails. + * + * @return true if this LoginModule's own login and commit + * attempts succeeded, or false otherwise. + */ + public boolean commit() throws LoginException { + if (succeeded == false) { + return false; + } else { + // add a Principal (authenticated identity) + // to the Subject + + // assume the user we authenticated is the SamplePrincipal + userPrincipal = new SamplePrincipal(username); + if (!subject.getPrincipals().contains(userPrincipal)) + subject.getPrincipals().add(userPrincipal); + + if (debug) { + System.out.println("\t\t[SampleLoginModule] " + + "added SamplePrincipal to Subject"); + } + + // in any case, clean out state + username = null; + for (int i = 0; i < password.length; i++) + password[i] = ' '; + password = null; + + commitSucceeded = true; + return true; + } + } + + /** + *

    This method is called if the LoginContext's + * overall authentication failed. + * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules + * did not succeed). + * + *

    If this LoginModule's own authentication attempt + * succeeded (checked by retrieving the private state saved by the + * login and commit methods), + * then this method cleans up any state that was originally saved. + * + *

    + * + * @exception LoginException if the abort fails. + * + * @return false if this LoginModule's own login and/or commit attempts + * failed, and true otherwise. + */ + public boolean abort() throws LoginException { + if (succeeded == false) { + return false; + } else if (succeeded == true && commitSucceeded == false) { + // login succeeded but overall authentication failed + succeeded = false; + username = null; + if (password != null) { + for (int i = 0; i < password.length; i++) + password[i] = ' '; + password = null; + } + userPrincipal = null; + } else { + // overall authentication succeeded and commit succeeded, + // but someone else's commit failed + logout(); + } + return true; + } + + /** + * Logout the user. + * + *

    This method removes the SamplePrincipal + * that was added by the commit method. + * + *

    + * + * @exception LoginException if the logout fails. + * + * @return true in all cases since this LoginModule + * should not be ignored. + */ + public boolean logout() throws LoginException { + + subject.getPrincipals().remove(userPrincipal); + succeeded = false; + succeeded = commitSucceeded; + username = null; + if (password != null) { + for (int i = 0; i < password.length; i++) + password[i] = ' '; + password = null; + } + userPrincipal = null; + return true; + } +} \ No newline at end of file diff --git a/security/TPNote/Notes+Examples/revision/revision/tp2/partie1/sample/principal/SamplePrincipal.java b/security/TPNote/Notes+Examples/revision/revision/tp2/partie1/sample/principal/SamplePrincipal.java new file mode 100644 index 0000000..29621e7 --- /dev/null +++ b/security/TPNote/Notes+Examples/revision/revision/tp2/partie1/sample/principal/SamplePrincipal.java @@ -0,0 +1,144 @@ +/* + * + * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * -Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * -Redistribution in binary form must reproduct the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Oracle nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any + * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY + * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY + * DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT OF OR + * RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR + * ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE + * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, + * SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER + * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF + * THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that Software is not designed, licensed or + * intended for use in the design, construction, operation or + * maintenance of any nuclear facility. + */ + +package sample.principal; + +import java.security.Principal; + +/** + *

    This class implements the Principal interface + * and represents a Sample user. + * + *

    Principals such as this SamplePrincipal + * may be associated with a particular Subject + * to augment that Subject with an additional + * identity. Refer to the Subject class for more information + * on how to achieve this. Authorization decisions can then be based upon + * the Principals associated with a Subject. + * + * @see java.security.Principal + * @see javax.security.auth.Subject + */ +public class SamplePrincipal implements Principal, java.io.Serializable { + + /** + * @serial + */ + private String name; + + /** + * Create a SamplePrincipal with a Sample username. + * + *

    + * + * @param name the Sample username for this user. + * + * @exception NullPointerException if the name + * is null. + */ + public SamplePrincipal(String name) { + if (name == null) + throw new NullPointerException("illegal null input"); + + this.name = name; + } + + /** + * Return the Sample username for this SamplePrincipal. + * + *

    + * + * @return the Sample username for this SamplePrincipal + */ + public String getName() { + return name; + } + + /** + * Return a string representation of this SamplePrincipal. + * + *

    + * + * @return a string representation of this SamplePrincipal. + */ + public String toString() { + return("SamplePrincipal: " + name); + } + + /** + * Compares the specified Object with this SamplePrincipal + * for equality. Returns true if the given object is also a + * SamplePrincipal and the two SamplePrincipals + * have the same username. + * + *

    + * + * @param o Object to be compared for equality with this + * SamplePrincipal. + * + * @return true if the specified Object is equal equal to this + * SamplePrincipal. + */ + public boolean equals(Object o) { + if (o == null) + return false; + + if (this == o) + return true; + + if (!(o instanceof SamplePrincipal)) + return false; + SamplePrincipal that = (SamplePrincipal)o; + + if (this.getName().equals(that.getName())) + return true; + return false; + } + + /** + * Return a hash code for this SamplePrincipal. + * + *

    + * + * @return a hash code for this SamplePrincipal. + */ + public int hashCode() { + return name.hashCode(); + } +} \ No newline at end of file diff --git a/security/TPNote/Notes+Examples/revision/revision/tp2/partie2/.policy b/security/TPNote/Notes+Examples/revision/revision/tp2/partie2/.policy new file mode 100644 index 0000000..f5207c8 --- /dev/null +++ b/security/TPNote/Notes+Examples/revision/revision/tp2/partie2/.policy @@ -0,0 +1,7 @@ +grant codebase "file:./SampleLM.jar" { + permission javax.security.auth.AuthPermission "modifyPrincipals"; +}; + +grant codebase "file:./SampleAcn.jar" { + permission javax.security.auth.AuthPermission "createLoginContext.Sample"; +}; diff --git a/security/TPNote/Notes+Examples/revision/revision/tp2/partie2/SampleAcn.jar b/security/TPNote/Notes+Examples/revision/revision/tp2/partie2/SampleAcn.jar new file mode 100644 index 0000000000000000000000000000000000000000..5522f7e829f099939d70f1c558656893407e171b GIT binary patch literal 3266 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 TNq*)LU0!?y0Kiq6pWZ(JRDa26 literal 0 HcmV?d00001 diff --git a/security/TPNote/Notes+Examples/revision/revision/tp2/partie2/jaas.config b/security/TPNote/Notes+Examples/revision/revision/tp2/partie2/jaas.config new file mode 100644 index 0000000..deda887 --- /dev/null +++ b/security/TPNote/Notes+Examples/revision/revision/tp2/partie2/jaas.config @@ -0,0 +1,5 @@ +/** Login Configuration for the JAAS Sample Application **/ + +Sample { + sample.module.SampleLoginModule required debug=true; +}; \ No newline at end of file diff --git a/security/TPNote/Notes+Examples/revision/revision/tp2/partie2/run.sh b/security/TPNote/Notes+Examples/revision/revision/tp2/partie2/run.sh new file mode 100644 index 0000000..fb7bf3f --- /dev/null +++ b/security/TPNote/Notes+Examples/revision/revision/tp2/partie2/run.sh @@ -0,0 +1,28 @@ +# Reset +rm \ + ./SampleAcn.jar \ + ./SampleLM.jar + +# Compile Java files +javac \ + sample/SampleAcn.java \ + sample/module/SampleLoginModule.java \ + sample/principal/SamplePrincipal.java + +# Crée deux fichier Jar (SampleAcn et SampleLM) +jar -cvf SampleAcn.jar sample/SampleAcn.class sample/MyCallbackHandler.class +jar -cvf SampleLM.jar sample/module/SampleLoginModule.class sample/principal/SamplePrincipal.class + +# Supprime les artéfacts +rm \ + ./sample/MyCallbackHandler.class \ + ./sample/SampleAcn.class \ + ./sample/module/SampleLoginModule.class \ + ./sample/principal/SamplePrincipal.class \ + +# Exécute +java -classpath SampleAcn.jar:SampleLM.jar \ + -Djava.security.manager \ + -Djava.security.policy==.policy \ + -Djava.security.auth.login.config==jaas.config \ + sample.SampleAcn \ No newline at end of file diff --git a/security/TPNote/Notes+Examples/revision/revision/tp2/partie2/sample/SampleAcn.java b/security/TPNote/Notes+Examples/revision/revision/tp2/partie2/sample/SampleAcn.java new file mode 100644 index 0000000..f2b78aa --- /dev/null +++ b/security/TPNote/Notes+Examples/revision/revision/tp2/partie2/sample/SampleAcn.java @@ -0,0 +1,237 @@ +/* + * + * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * -Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * -Redistribution in binary form must reproduct the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Oracle nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any + * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY + * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY + * DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT OF OR + * RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR + * ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE + * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, + * SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER + * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF + * THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that Software is not designed, licensed or + * intended for use in the design, construction, operation or + * maintenance of any nuclear facility. + */ + +package sample; + +import java.io.*; +import java.util.*; +import javax.security.auth.login.*; +import javax.security.auth.*; +import javax.security.auth.callback.*; + +/** + *

    This Sample application attempts to authenticate a user + * and reports whether or not the authentication was successful. + */ +public class SampleAcn { + + /** + * Attempt to authenticate the user. + * + *

    + * + * @param args input arguments for this application. These are ignored. + */ + public static void main(String[] args) { + + // Obtain a LoginContext, needed for authentication. Tell it + // to use the LoginModule implementation specified by the + // entry named "Sample" in the JAAS login configuration + // file and to also use the specified CallbackHandler. + LoginContext lc = null; + try { + lc = new LoginContext("Sample", new MyCallbackHandler()); + } catch (LoginException le) { + System.err.println("Cannot create LoginContext. " + le.getMessage()); + System.exit(-1); + } catch (SecurityException se) { + System.err.println("Cannot create LoginContext. " + se.getMessage()); + System.exit(-1); + } + + // the user has 3 attempts to authenticate successfully + int i; + for (i = 0; i < 3; i++) { + try { + + // attempt authentication + lc.login(); + + // if we return with no exception, authentication succeeded + break; + + } catch (LoginException le) { + + System.err.println("Authentication failed:"); + System.err.println(" " + le.getMessage()); + try { + Thread.currentThread().sleep(3000); + } catch (Exception e) { + // ignore + } + + } + } + + // did they fail three times? + if (i == 3) { + System.out.println("Sorry"); + System.exit(-1); + } + + System.out.println("Authentication succeeded!"); + + } +} + + +/** + * The application implements the CallbackHandler. + * + *

    This application is text-based. Therefore it displays information + * to the user using the OutputStreams System.out and System.err, + * and gathers input from the user using the InputStream System.in. + */ +class MyCallbackHandler implements CallbackHandler { + + /** + * Invoke an array of Callbacks. + * + *

    + * + * @param callbacks an array of Callback objects which contain + * the information requested by an underlying security + * service to be retrieved or displayed. + * + * @exception java.io.IOException if an input or output error occurs.

    + * + * @exception UnsupportedCallbackException if the implementation of this + * method does not support one or more of the Callbacks + * specified in the callbacks parameter. + */ + public void handle(Callback[] callbacks) + throws IOException, UnsupportedCallbackException { + + for (int i = 0; i < callbacks.length; i++) { + if (callbacks[i] instanceof TextOutputCallback) { + + // display the message according to the specified type + TextOutputCallback toc = (TextOutputCallback)callbacks[i]; + switch (toc.getMessageType()) { + case TextOutputCallback.INFORMATION: + System.out.println(toc.getMessage()); + break; + case TextOutputCallback.ERROR: + System.out.println("ERROR: " + toc.getMessage()); + break; + case TextOutputCallback.WARNING: + System.out.println("WARNING: " + toc.getMessage()); + break; + default: + throw new IOException("Unsupported message type: " + toc.getMessageType()); + } + + } else if (callbacks[i] instanceof NameCallback) { + + // prompt the user for a username + NameCallback nc = (NameCallback)callbacks[i]; + + System.err.print(nc.getPrompt()); + System.err.flush(); + nc.setName((new BufferedReader + (new InputStreamReader(System.in))).readLine()); + + } else if (callbacks[i] instanceof PasswordCallback) { + + // prompt the user for sensitive information + PasswordCallback pc = (PasswordCallback)callbacks[i]; + System.err.print(pc.getPrompt()); + System.err.flush(); + pc.setPassword(readPassword(System.in)); + + } else { + throw new UnsupportedCallbackException + (callbacks[i], "Unrecognized Callback"); + } + } + } + + // Reads user password from given input stream. + private char[] readPassword(InputStream in) throws IOException { + + char[] lineBuffer; + char[] buf; + int i; + + buf = lineBuffer = new char[128]; + + int room = buf.length; + int offset = 0; + int c; + +loop: while (true) { + switch (c = in.read()) { + case -1: + case '\n': + break loop; + + case '\r': + int c2 = in.read(); + if ((c2 != '\n') && (c2 != -1)) { + if (!(in instanceof PushbackInputStream)) { + in = new PushbackInputStream(in); + } + ((PushbackInputStream)in).unread(c2); + } else + break loop; + + default: + if (--room < 0) { + buf = new char[offset + 128]; + room = buf.length - offset - 1; + System.arraycopy(lineBuffer, 0, buf, 0, offset); + Arrays.fill(lineBuffer, ' '); + lineBuffer = buf; + } + buf[offset++] = (char) c; + break; + } + } + + if (offset == 0) { + return null; + } + + char[] ret = new char[offset]; + System.arraycopy(buf, 0, ret, 0, offset); + Arrays.fill(buf, ' '); + + return ret; + } +} \ No newline at end of file diff --git a/security/TPNote/Notes+Examples/revision/revision/tp2/partie2/sample/module/SampleLoginModule.java b/security/TPNote/Notes+Examples/revision/revision/tp2/partie2/sample/module/SampleLoginModule.java new file mode 100644 index 0000000..0f4b88e --- /dev/null +++ b/security/TPNote/Notes+Examples/revision/revision/tp2/partie2/sample/module/SampleLoginModule.java @@ -0,0 +1,337 @@ +/* + * + * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * -Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * -Redistribution in binary form must reproduct the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Oracle nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any + * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY + * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY + * DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT OF OR + * RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR + * ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE + * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, + * SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER + * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF + * THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that Software is not designed, licensed or + * intended for use in the design, construction, operation or + * maintenance of any nuclear facility. + */ + +package sample.module; + +import java.util.*; +import java.io.IOException; +import javax.security.auth.*; +import javax.security.auth.callback.*; +import javax.security.auth.login.*; +import javax.security.auth.spi.*; +import sample.principal.SamplePrincipal; + +/** + *

    This sample LoginModule authenticates users with a password. + * + *

    This LoginModule only recognizes one user: testUser + *

    testUser's password is: testPassword + * + *

    If testUser successfully authenticates itself, + * a SamplePrincipal with the testUser's user name + * is added to the Subject. + * + *

    This LoginModule recognizes the debug option. + * If set to true in the login Configuration, + * debug messages will be output to the output stream, System.out. + * + */ +public class SampleLoginModule implements LoginModule { + + // initial state + private Subject subject; + private CallbackHandler callbackHandler; + private Map sharedState; + private Map options; + + // configurable option + private boolean debug = false; + + // the authentication status + private boolean succeeded = false; + private boolean commitSucceeded = false; + + // username and password + private String username; + private char[] password; + + // testUser's SamplePrincipal + private SamplePrincipal userPrincipal; + + /** + * Initialize this LoginModule. + * + *

    + * + * @param subject the Subject to be authenticated.

    + * + * @param callbackHandler a CallbackHandler for communicating + * with the end user (prompting for user names and + * passwords, for example).

    + * + * @param sharedState shared LoginModule state.

    + * + * @param options options specified in the login + * Configuration for this particular + * LoginModule. + */ + public void initialize(Subject subject, + CallbackHandler callbackHandler, + Map sharedState, + Map options) { + + this.subject = subject; + this.callbackHandler = callbackHandler; + this.sharedState = sharedState; + this.options = options; + + // initialize any configured options + debug = "true".equalsIgnoreCase((String)options.get("debug")); + } + + /** + * Authenticate the user by prompting for a user name and password. + * + *

    + * + * @return true in all cases since this LoginModule + * should not be ignored. + * + * @exception FailedLoginException if the authentication fails.

    + * + * @exception LoginException if this LoginModule + * is unable to perform the authentication. + */ + public boolean login() throws LoginException { + + // prompt for a user name and password + if (callbackHandler == null) + throw new LoginException("Error: no CallbackHandler available " + + "to garner authentication information from the user"); + + Callback[] callbacks = new Callback[2]; + callbacks[0] = new NameCallback("user name: "); + callbacks[1] = new PasswordCallback("password: ", false); + + try { + callbackHandler.handle(callbacks); + username = ((NameCallback)callbacks[0]).getName(); + char[] tmpPassword = ((PasswordCallback)callbacks[1]).getPassword(); + if (tmpPassword == null) { + // treat a NULL password as an empty password + tmpPassword = new char[0]; + } + password = new char[tmpPassword.length]; + System.arraycopy(tmpPassword, 0, + password, 0, tmpPassword.length); + ((PasswordCallback)callbacks[1]).clearPassword(); + + } catch (java.io.IOException ioe) { + throw new LoginException(ioe.toString()); + } catch (UnsupportedCallbackException uce) { + throw new LoginException("Error: " + uce.getCallback().toString() + + " not available to garner authentication information " + + "from the user"); + } + + // print debugging information + if (debug) { + System.out.println("\t\t[SampleLoginModule] " + + "user entered user name: " + + username); + System.out.print("\t\t[SampleLoginModule] " + + "user entered password: "); + for (int i = 0; i < password.length; i++) + System.out.print(password[i]); + System.out.println(); + } + + // verify the username/password + boolean usernameCorrect = false; + boolean passwordCorrect = false; + if (username.equals("testUser")) + usernameCorrect = true; + if (usernameCorrect && + password.length == 12 && + password[0] == 't' && + password[1] == 'e' && + password[2] == 's' && + password[3] == 't' && + password[4] == 'P' && + password[5] == 'a' && + password[6] == 's' && + password[7] == 's' && + password[8] == 'w' && + password[9] == 'o' && + password[10] == 'r' && + password[11] == 'd') { + + // authentication succeeded!!! + passwordCorrect = true; + if (debug) + System.out.println("\t\t[SampleLoginModule] " + + "authentication succeeded"); + succeeded = true; + return true; + } else { + + // authentication failed -- clean out state + if (debug) + System.out.println("\t\t[SampleLoginModule] " + + "authentication failed"); + succeeded = false; + username = null; + for (int i = 0; i < password.length; i++) + password[i] = ' '; + password = null; + if (!usernameCorrect) { + throw new FailedLoginException("User Name Incorrect"); + } else { + throw new FailedLoginException("Password Incorrect"); + } + } + } + + /** + *

    This method is called if the LoginContext's + * overall authentication succeeded + * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules + * succeeded). + * + *

    If this LoginModule's own authentication attempt + * succeeded (checked by retrieving the private state saved by the + * login method), then this method associates a + * SamplePrincipal + * with the Subject located in the + * LoginModule. If this LoginModule's own + * authentication attempted failed, then this method removes + * any state that was originally saved. + * + *

    + * + * @exception LoginException if the commit fails. + * + * @return true if this LoginModule's own login and commit + * attempts succeeded, or false otherwise. + */ + public boolean commit() throws LoginException { + if (succeeded == false) { + return false; + } else { + // add a Principal (authenticated identity) + // to the Subject + + // assume the user we authenticated is the SamplePrincipal + userPrincipal = new SamplePrincipal(username); + if (!subject.getPrincipals().contains(userPrincipal)) + subject.getPrincipals().add(userPrincipal); + + if (debug) { + System.out.println("\t\t[SampleLoginModule] " + + "added SamplePrincipal to Subject"); + } + + // in any case, clean out state + username = null; + for (int i = 0; i < password.length; i++) + password[i] = ' '; + password = null; + + commitSucceeded = true; + return true; + } + } + + /** + *

    This method is called if the LoginContext's + * overall authentication failed. + * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules + * did not succeed). + * + *

    If this LoginModule's own authentication attempt + * succeeded (checked by retrieving the private state saved by the + * login and commit methods), + * then this method cleans up any state that was originally saved. + * + *

    + * + * @exception LoginException if the abort fails. + * + * @return false if this LoginModule's own login and/or commit attempts + * failed, and true otherwise. + */ + public boolean abort() throws LoginException { + if (succeeded == false) { + return false; + } else if (succeeded == true && commitSucceeded == false) { + // login succeeded but overall authentication failed + succeeded = false; + username = null; + if (password != null) { + for (int i = 0; i < password.length; i++) + password[i] = ' '; + password = null; + } + userPrincipal = null; + } else { + // overall authentication succeeded and commit succeeded, + // but someone else's commit failed + logout(); + } + return true; + } + + /** + * Logout the user. + * + *

    This method removes the SamplePrincipal + * that was added by the commit method. + * + *

    + * + * @exception LoginException if the logout fails. + * + * @return true in all cases since this LoginModule + * should not be ignored. + */ + public boolean logout() throws LoginException { + + subject.getPrincipals().remove(userPrincipal); + succeeded = false; + succeeded = commitSucceeded; + username = null; + if (password != null) { + for (int i = 0; i < password.length; i++) + password[i] = ' '; + password = null; + } + userPrincipal = null; + return true; + } +} \ No newline at end of file diff --git a/security/TPNote/Notes+Examples/revision/revision/tp2/partie2/sample/principal/SamplePrincipal.java b/security/TPNote/Notes+Examples/revision/revision/tp2/partie2/sample/principal/SamplePrincipal.java new file mode 100644 index 0000000..e205bd0 --- /dev/null +++ b/security/TPNote/Notes+Examples/revision/revision/tp2/partie2/sample/principal/SamplePrincipal.java @@ -0,0 +1,141 @@ +/* + * + * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * -Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * -Redistribution in binary form must reproduct the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Oracle nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any + * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY + * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY + * DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT OF OR + * RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR + * ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE + * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, + * SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER + * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF + * THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that Software is not designed, licensed or + * intended for use in the design, construction, operation or + * maintenance of any nuclear facility. + */ + +package sample.principal; + +import java.security.Principal; + +/** + *

    This class implements the Principal interface + * and represents a Sample user. + * + *

    Principals such as this SamplePrincipal + * may be associated with a particular Subject + * to augment that Subject with an additional + * identity. Refer to the Subject class for more information + * on how to achieve this. Authorization decisions can then be based upon + * the Principals associated with a Subject. + * + * @see java.security.Principal + * @see javax.security.auth.Subject + */ +public class SamplePrincipal implements Principal, java.io.Serializable { + + /** + * @serial + */ + private String name; + + /** + * Create a SamplePrincipal with a Sample username. + * + *

    + * + * @param name the Sample username for this user. + * + * @exception NullPointerException if the name + * is null. + */ + public SamplePrincipal(String name) { + if (name == null) + throw new NullPointerException("illegal null input"); + + this.name = name; + } + + /** + * Return the Sample username for this SamplePrincipal. + * + *

    + * + * @return the Sample username for this SamplePrincipal + */ + public String getName() { + return name; + } + + /** + * Return a string representation of this SamplePrincipal. + * + *

    + * + * @return a string representation of this SamplePrincipal. + */ + public String toString() { + return("SamplePrincipal: " + name); + } + + /** + * Compares the specified Object with this SamplePrincipal + * for equality. Returns true if the given object is also a + * SamplePrincipal and the two SamplePrincipals + * have the same username. + * + *

    + * + * @param o Object to be compared for equality with this + * SamplePrincipal. + * + * @return true if the specified Object is equal equal to this + * SamplePrincipal. + */ + public boolean equals(Object o) { + if (o == null) return false; + if (this == o) return true; + + if (!(o instanceof SamplePrincipal)) + return false; + SamplePrincipal that = (SamplePrincipal)o; + + if (this.getName().equals(that.getName())) + return true; + return false; + } + + /** + * Return a hash code for this SamplePrincipal. + * + *

    + * + * @return a hash code for this SamplePrincipal. + */ + public int hashCode() { + return name.hashCode(); + } +} \ No newline at end of file diff --git a/security/TPNote/Notes+Examples/revision/revision/tp2/partie3/SampleAction.jar b/security/TPNote/Notes+Examples/revision/revision/tp2/partie3/SampleAction.jar new file mode 100644 index 0000000000000000000000000000000000000000..34c9ae8eddeec6454d14d7b787b47e91031e231a GIT binary patch literal 1196 zcmWIWW@h1HVBlb2NZgwq$$$hn8CV#6T|*poJ^kGD|D9rB2mmS-Vc_84z)&gz)CO1T z>*(j{<{BKL=j-;__snS@Z(Y5MyxzK6=gyqp9At3C_`%a6JuhD!Pv48BtF{CgFm=6< z)XMlFuB!HYiI&B4anUE@s?!)mvp*GmEMf%O$P?3wMx#lJp(KgrL)nbTIt zsmSZgHtXV{3tRJLBMgrheNWOa|6Unpv_!A94d)0<;wPL$i;RVXXVv-Xtm*={BN;7xkWcRLKWye-`Mv{UGNN^4@0 zR_yf1psu|?N)~H6-M^5%z+d%+eiZ9Gk-Te@*5}MzK3iWm{8!?a$6alV%;AP7E)?_W zv#niXa$NP%^U!-24PB0$w)@WXNYLO*mVso?Sil7 ziCfue#_BurwSt1#mWeKYwqRS+d8r+p(N_xVGJap;xBBPi-m~ze=%p)#?TJPoW^T(q zWn;cM_59;?Cil75JNTTP^Y-GImhjH39p3VU!>l2!VI`!n;+*R}4N`oJLnJAf=$}JtX zl8rCj<>u+4tI}=ns>A|CeSdFOY5B4=eX7}xGu?C6Kh|7od0U|PUW%1aiq-4AMy1;n zB##yAWP7aqxZa@W@6zPm?28U$A6}j3a*Au$p${AD_LwGY{j%!mGnse&OItOjcz-;m zyF;U3chIBf2kx7hW$ZF^y;L-(N7vHyd_-~VJ5|}!-*>Km$a?rkec;szcCs&818%L< zl2|-rvH1Cd{&{_qzPx%_<8VvB(`{4bGl@6cu@Z8ZZVE{}e^JwN-1G%|i-ttRe=gli z|9I!BzhLYuh3YdLvS`Am(|?4ZRH*U_}dp;Z=6^a=BJ<2ZRc6#WsJvZ)RI8+jS z*vib{13M^-_<2arxWmN2@SO#eMHrd57;xulU_L6aEtKnPtxdWe)z1O-JvMS7F2^cIQ~DFV_% zGogtfqKKggN)aOnh!0-5I`6&vn>lm#nX~p=1eY7Q~x!GHD9e&Abyrs?Z8C8wj zuu<6i(3Uv5U$?Jx9k@K$Unmf~a82XzgVbt4;AY6oe9N!49~`%>ZgS|-z~rNG(dHsD z#UzLvd#3X$`+WGpwLzW=TaPzozlt>6v_JAOgYSe5$fa*zD_hJt_Ujej?_?Mq&JGqT z9YhemFDLVBrcZjg3S2i}Ztqr=MvE!O&NGd!!)1TkF{$_%D8zYN>J>V-N5Qq9)Cf`l z`foyzDvyjap37UH(nIxKQJM)1az}L2NNs5L9+FTHHJ4Rfs7J6L%U!(pt$uZsDo5JE z`l<;y>(hl`whU9uBt%~i&aoRL*{yZQ)8yd%=<{fAZHR-cGPx=_cu(`P|LdJJnz9XX!jw6c19!_6_^jND^eXDuBBjhMVO-hxm zlbo%R^z7V9*YMNop2v0IiyS_2X4T|g%n7y+QH;6-Y-TOo17*jj+hjXbjV)BUo zEoUq>v_VDf`*meNAXO%q*Y(;2lh3dp6mUn=sqUoa`$-kp}+EgH|J&WGC>bei{sCmNs!Yy6j^Y#le*R6*#-=lF!r zgHpAzI&~}-8R-6yxXN>`d$#zu-k%_5>iIPtR%=hkjB`h?PDpB5B?jQg{^@(+EB?@K z@1#QZ0+_Z_hHiNFn@O1=^2MMU7h#{5oKsy-&RU7Z2JsRY?s(ahzY?C&EDJT6Bx?1! zS_sMykEC8R|JAozGp0texb-Rsj|xX-QWh_APw8|MY$$~YF{A48a$~z-ZrZStdAD!q zl4x3{DJzD6C-!z%QKh#KuULfnw|x|~Bh#JT1WWRxa#M1Vr9p3IU%iaWNJc0pZvCiD z*-DP6OQQ%Wiq%)VtoJ1(d7wwT;*%m(ay|-0?Lo_1ZSC1AvU-0A&&+NfGQgGwGzk1U z?L9tujxnZ1`<#!x_U#A07ilbqH?(%v8b1kc(5BO*>WRTqz?7M^9Sw|&K zISq;N@5p6g5OiO{p1z~!DNH~VPIG+;m(pCM&UUwgt^x4m2W{?T|+(jMZIzZ!%twt46)b zC*M~a5GEq;M3tW*nyWU3AZ+!XVyQo5j%S150bAdDtFFU;!VrUq3|u8e!rsCrTx>uE zD{yI?9rX=6>7%XSr?Dt8UCA{?@fgaKG4<(FNakpL(6#t1B|JpGBb1< z1cGfZve_9PSJ;`+u?y0|eUzNuCTYAx-V|>Ui23q%)sIshkz9MUf5yu1?TAC%&F2>< zdLolej*T${St4atGjUDah9N$&A7St@lq$` z0?7dJVyYxhn9TUufybZe(Og>>f#GOqYC|!`3DV>AV2wp7vd?Zmf0tkJ;a@van+^6f z#552_hoTmRAK!j9_{hvNYuGw?8UI4CAA#L0WGP%KRJLF`cN|4eYJDhjR#~3czGv{z zB-!1g@?4gw)2%V4Flh*h?jv2#zF^nljr3}1XhEI%q4X&vZc^r@KF|OFZ6`4McS!L4 zh6M74wlfCf;_T|9?~J{MaSQk#Sa@ML-5?QNo$k+>zTKvQarwkF%s1eR(uu8XSE=LeN|^6Kiaq5f{yLU9=|?{+usbHF`%F?%MZ`I0Xv8Ca!5&q1PZ z!0a`@8cWN8j{Kg@-4>AFWoji)kMZO_1_yZfT~zO9me^9yCT-9jb?$P$`>o!1v9YSA zp)*u`U<(0RUH#Ax?@?jNu zQeiIog?!RbuEY{8r|ejqfm%RDS*%E4u}kn&nzLb*mkg)JWWMCcnLc|e1tfi0Syz|` zIx#n{Y{mS}N}%l&goZVJ+|^x+n70dUQ#asx6Pnp%$2m*yb=3#Ck*@*P6|d zt*e7rvz5dK^m0FJ&1hV13jL5OA~X`(r>IiQP;A#N8=GA`VJ)hx;^vSjH-gfcp}}7r z;vY3G9n_!5I~co*zUabL(T9msemcZapH2?IuNYX#jD2^D-nUaj$H7?I(^`4yN_k6P z)PbL7imi#}>(>;GsBWAEhwL0tYa^7jf!&NO5$k;bxdD9vPud*ocvQ?c0 z8ED+QFY_K)<}sAs)58GPa8>cZT&QeponTO86+*v!gaw11O>Cx{wF!Ni!X%e_-H*F} z=Rn+OGN@7kKM)Qz6g6@2c9p0b7HBZ;_kRp5lg7QRQDiYBZRjDHW!n_dlZ{0gx8=n? z)4Sr<2{RNH=V&~HtTQETRjFZE< zUXBKp!!quNsS8ZAOblMlKRPL0ei4XHU4joMcn!yEayI)Hm%~{h-BFD{*P8PVSX~}0 zPxC83Kt)L!E^&t$E~L+0CH=?>fFgpSM%45!*iD%Lj0A8==E^s!Y79cTO<}_Do^CtF?vow& zEtTAd3);kI?PiO{*;9@yMe$p{5*+WA+}?B_xl?M>e)Xf6pO8W4 zqr1hBp6coKI=D(AoGx|jfuJbbUix-;bUY()od(0TE%5U$cwhGBSTIx<1KDJsaD#6> zF~3+e7d8tDR8TtOK7N>XA#&RG5Ff-^(75jw$|t?3Oa4W7N-C@(0q95z04Oq^l8Ool z0{pvwo#5(^{G(X^Wn)x8PQY&;`_qz6ee8E6PL}^{{lm^qhyU5(PlTS@)bG@tEdPJE p`rkeNyxb{le`osS%KzQtU(jo2L~~LDIMGgO05cT;5W#%<^&jIDc+~&^ literal 0 HcmV?d00001 diff --git a/security/TPNote/Notes+Examples/revision/revision/tp2/partie3/SampleLM.jar b/security/TPNote/Notes+Examples/revision/revision/tp2/partie3/SampleLM.jar new file mode 100644 index 0000000000000000000000000000000000000000..0109f7de35ec11a6f0302a363c94a4a7e5e7dd6a GIT binary patch literal 3921 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 This is a Sample PrivilegedAction implementation, designed to be + * used with the Sample application. + * + */ +public class SampleAction implements PrivilegedAction { + + /** + *

    This Sample PrivilegedAction performs the following operations: + *

      + *
    • Access the System property, java.home + *
    • Access the System property, user.home + *
    • Access the file, foo.txt + *
    + * + * @return null in all cases. + * + * @exception SecurityException if the caller does not have permission + * to perform the operations listed above. + */ + public Object run() { + System.out.println("java.home : " + System.getProperty("java.home")); + System.out.println("user.home : " + System.getProperty("user.home")); + + File f = new File("foo.txt"); + System.out.print("foo.txt does "); + if (!f.exists()) System.out.print("not "); + System.out.println("exist in the current working directory."); + return null; + } +} \ No newline at end of file diff --git a/security/TPNote/Notes+Examples/revision/revision/tp2/partie3/sample/SampleAzn.java b/security/TPNote/Notes+Examples/revision/revision/tp2/partie3/sample/SampleAzn.java new file mode 100644 index 0000000..e07ec79 --- /dev/null +++ b/security/TPNote/Notes+Examples/revision/revision/tp2/partie3/sample/SampleAzn.java @@ -0,0 +1,265 @@ +/* + * + * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * -Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * -Redistribution in binary form must reproduct the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Oracle nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any + * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY + * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY + * DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT OF OR + * RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR + * ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE + * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, + * SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER + * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF + * THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that Software is not designed, licensed or + * intended for use in the design, construction, operation or + * maintenance of any nuclear facility. + */ + +package sample; + +import java.io.*; +import java.util.*; +import java.security.Principal; +import java.security.PrivilegedAction; +import javax.security.auth.*; +import javax.security.auth.callback.*; +import javax.security.auth.login.*; +import javax.security.auth.spi.*; +import com.sun.security.auth.*; + +/** + *

    This Sample application attempts to authenticate a user + * and executes a SampleAction as that user. + * + *

    If the user successfully authenticates itself, + * the username and number of Credentials is displayed. + */ +public class SampleAzn { + + /** + * Attempt to authenticate the user. + * + *

    + * + * @param args input arguments for this application. These are ignored. + */ + public static void main(String[] args) { + + // Obtain a LoginContext, needed for authentication. Tell it + // to use the LoginModule implementation specified by the + // entry named "Sample" in the JAAS login configuration + // file and to also use the specified CallbackHandler. + LoginContext lc = null; + try { + lc = new LoginContext("Sample", new MyCallbackHandler()); + } catch (LoginException le) { + System.err.println("Cannot create LoginContext. " + + le.getMessage()); + System.exit(-1); + } catch (SecurityException se) { + System.err.println("Cannot create LoginContext. " + + se.getMessage()); + System.exit(-1); + } + + // the user has 3 attempts to authenticate successfully + int i; + for (i = 0; i < 3; i++) { + try { + + // attempt authentication + lc.login(); + + // if we return with no exception, authentication succeeded + break; + + } catch (LoginException le) { + + System.err.println("Authentication failed:"); + System.err.println(" " + le.getMessage()); + try { + Thread.currentThread().sleep(3000); + } catch (Exception e) { + // ignore + } + + } + } + + // did they fail three times? + if (i == 3) { + System.out.println("Sorry"); + System.exit(-1); + } + + System.out.println("Authentication succeeded!"); + + Subject mySubject = lc.getSubject(); + + // let's see what Principals we have + Iterator principalIterator = mySubject.getPrincipals().iterator(); + System.out.println("Authenticated user has the following Principals:"); + while (principalIterator.hasNext()) { + Principal p = (Principal)principalIterator.next(); + System.out.println("\t" + p.toString()); + } + + System.out.println("User has " + + mySubject.getPublicCredentials().size() + + " Public Credential(s)"); + + // now try to execute the SampleAction as the authenticated Subject + PrivilegedAction action = new SampleAction(); + Subject.doAsPrivileged(mySubject, action, null); + + System.exit(0); + } +} + +/** + * A CallbackHandler implemented by the application. + * + *

    This application is text-based. Therefore it displays information + * to the user using the OutputStreams System.out and System.err, + * and gathers input from the user using the InputStream System.in. + */ +class MyCallbackHandler implements CallbackHandler { + + /** + * Invoke an array of Callbacks. + * + *

    + * + * @param callbacks an array of Callback objects which contain + * the information requested by an underlying security + * service to be retrieved or displayed. + * + * @exception java.io.IOException if an input or output error occurs.

    + * + * @exception UnsupportedCallbackException if the implementation of this + * method does not support one or more of the Callbacks + * specified in the callbacks parameter. + */ + public void handle(Callback[] callbacks) + throws IOException, UnsupportedCallbackException { + + for (int i = 0; i < callbacks.length; i++) { + if (callbacks[i] instanceof TextOutputCallback) { + + // display the message according to the specified type + TextOutputCallback toc = (TextOutputCallback)callbacks[i]; + switch (toc.getMessageType()) { + case TextOutputCallback.INFORMATION: + System.out.println(toc.getMessage()); + break; + case TextOutputCallback.ERROR: + System.out.println("ERROR: " + toc.getMessage()); + break; + case TextOutputCallback.WARNING: + System.out.println("WARNING: " + toc.getMessage()); + break; + default: + throw new IOException("Unsupported message type: " + + toc.getMessageType()); + } + + } else if (callbacks[i] instanceof NameCallback) { + + // prompt the user for a username + NameCallback nc = (NameCallback)callbacks[i]; + + System.err.print(nc.getPrompt()); + System.err.flush(); + nc.setName((new BufferedReader + (new InputStreamReader(System.in))).readLine()); + + } else if (callbacks[i] instanceof PasswordCallback) { + + // prompt the user for sensitive information + PasswordCallback pc = (PasswordCallback)callbacks[i]; + System.err.print(pc.getPrompt()); + System.err.flush(); + pc.setPassword(readPassword(System.in)); + + } else { + throw new UnsupportedCallbackException + (callbacks[i], "Unrecognized Callback"); + } + } + } + + // Reads user password from given input stream. + private char[] readPassword(InputStream in) throws IOException { + + char[] lineBuffer; + char[] buf; + int i; + + buf = lineBuffer = new char[128]; + + int room = buf.length; + int offset = 0; + int c; + +loop: while (true) { + switch (c = in.read()) { + case -1: + case '\n': + break loop; + + case '\r': + int c2 = in.read(); + if ((c2 != '\n') && (c2 != -1)) { + if (!(in instanceof PushbackInputStream)) { + in = new PushbackInputStream(in); + } + ((PushbackInputStream)in).unread(c2); + } else + break loop; + + default: + if (--room < 0) { + buf = new char[offset + 128]; + room = buf.length - offset - 1; + System.arraycopy(lineBuffer, 0, buf, 0, offset); + Arrays.fill(lineBuffer, ' '); + lineBuffer = buf; + } + buf[offset++] = (char) c; + break; + } + } + + if (offset == 0) { + return null; + } + + char[] ret = new char[offset]; + System.arraycopy(buf, 0, ret, 0, offset); + Arrays.fill(buf, ' '); + + return ret; + } +} \ No newline at end of file diff --git a/security/TPNote/Notes+Examples/revision/revision/tp2/partie3/sample/module/SampleLoginModule.java b/security/TPNote/Notes+Examples/revision/revision/tp2/partie3/sample/module/SampleLoginModule.java new file mode 100644 index 0000000..0f4b88e --- /dev/null +++ b/security/TPNote/Notes+Examples/revision/revision/tp2/partie3/sample/module/SampleLoginModule.java @@ -0,0 +1,337 @@ +/* + * + * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * -Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * -Redistribution in binary form must reproduct the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Oracle nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any + * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY + * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY + * DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT OF OR + * RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR + * ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE + * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, + * SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER + * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF + * THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that Software is not designed, licensed or + * intended for use in the design, construction, operation or + * maintenance of any nuclear facility. + */ + +package sample.module; + +import java.util.*; +import java.io.IOException; +import javax.security.auth.*; +import javax.security.auth.callback.*; +import javax.security.auth.login.*; +import javax.security.auth.spi.*; +import sample.principal.SamplePrincipal; + +/** + *

    This sample LoginModule authenticates users with a password. + * + *

    This LoginModule only recognizes one user: testUser + *

    testUser's password is: testPassword + * + *

    If testUser successfully authenticates itself, + * a SamplePrincipal with the testUser's user name + * is added to the Subject. + * + *

    This LoginModule recognizes the debug option. + * If set to true in the login Configuration, + * debug messages will be output to the output stream, System.out. + * + */ +public class SampleLoginModule implements LoginModule { + + // initial state + private Subject subject; + private CallbackHandler callbackHandler; + private Map sharedState; + private Map options; + + // configurable option + private boolean debug = false; + + // the authentication status + private boolean succeeded = false; + private boolean commitSucceeded = false; + + // username and password + private String username; + private char[] password; + + // testUser's SamplePrincipal + private SamplePrincipal userPrincipal; + + /** + * Initialize this LoginModule. + * + *

    + * + * @param subject the Subject to be authenticated.

    + * + * @param callbackHandler a CallbackHandler for communicating + * with the end user (prompting for user names and + * passwords, for example).

    + * + * @param sharedState shared LoginModule state.

    + * + * @param options options specified in the login + * Configuration for this particular + * LoginModule. + */ + public void initialize(Subject subject, + CallbackHandler callbackHandler, + Map sharedState, + Map options) { + + this.subject = subject; + this.callbackHandler = callbackHandler; + this.sharedState = sharedState; + this.options = options; + + // initialize any configured options + debug = "true".equalsIgnoreCase((String)options.get("debug")); + } + + /** + * Authenticate the user by prompting for a user name and password. + * + *

    + * + * @return true in all cases since this LoginModule + * should not be ignored. + * + * @exception FailedLoginException if the authentication fails.

    + * + * @exception LoginException if this LoginModule + * is unable to perform the authentication. + */ + public boolean login() throws LoginException { + + // prompt for a user name and password + if (callbackHandler == null) + throw new LoginException("Error: no CallbackHandler available " + + "to garner authentication information from the user"); + + Callback[] callbacks = new Callback[2]; + callbacks[0] = new NameCallback("user name: "); + callbacks[1] = new PasswordCallback("password: ", false); + + try { + callbackHandler.handle(callbacks); + username = ((NameCallback)callbacks[0]).getName(); + char[] tmpPassword = ((PasswordCallback)callbacks[1]).getPassword(); + if (tmpPassword == null) { + // treat a NULL password as an empty password + tmpPassword = new char[0]; + } + password = new char[tmpPassword.length]; + System.arraycopy(tmpPassword, 0, + password, 0, tmpPassword.length); + ((PasswordCallback)callbacks[1]).clearPassword(); + + } catch (java.io.IOException ioe) { + throw new LoginException(ioe.toString()); + } catch (UnsupportedCallbackException uce) { + throw new LoginException("Error: " + uce.getCallback().toString() + + " not available to garner authentication information " + + "from the user"); + } + + // print debugging information + if (debug) { + System.out.println("\t\t[SampleLoginModule] " + + "user entered user name: " + + username); + System.out.print("\t\t[SampleLoginModule] " + + "user entered password: "); + for (int i = 0; i < password.length; i++) + System.out.print(password[i]); + System.out.println(); + } + + // verify the username/password + boolean usernameCorrect = false; + boolean passwordCorrect = false; + if (username.equals("testUser")) + usernameCorrect = true; + if (usernameCorrect && + password.length == 12 && + password[0] == 't' && + password[1] == 'e' && + password[2] == 's' && + password[3] == 't' && + password[4] == 'P' && + password[5] == 'a' && + password[6] == 's' && + password[7] == 's' && + password[8] == 'w' && + password[9] == 'o' && + password[10] == 'r' && + password[11] == 'd') { + + // authentication succeeded!!! + passwordCorrect = true; + if (debug) + System.out.println("\t\t[SampleLoginModule] " + + "authentication succeeded"); + succeeded = true; + return true; + } else { + + // authentication failed -- clean out state + if (debug) + System.out.println("\t\t[SampleLoginModule] " + + "authentication failed"); + succeeded = false; + username = null; + for (int i = 0; i < password.length; i++) + password[i] = ' '; + password = null; + if (!usernameCorrect) { + throw new FailedLoginException("User Name Incorrect"); + } else { + throw new FailedLoginException("Password Incorrect"); + } + } + } + + /** + *

    This method is called if the LoginContext's + * overall authentication succeeded + * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules + * succeeded). + * + *

    If this LoginModule's own authentication attempt + * succeeded (checked by retrieving the private state saved by the + * login method), then this method associates a + * SamplePrincipal + * with the Subject located in the + * LoginModule. If this LoginModule's own + * authentication attempted failed, then this method removes + * any state that was originally saved. + * + *

    + * + * @exception LoginException if the commit fails. + * + * @return true if this LoginModule's own login and commit + * attempts succeeded, or false otherwise. + */ + public boolean commit() throws LoginException { + if (succeeded == false) { + return false; + } else { + // add a Principal (authenticated identity) + // to the Subject + + // assume the user we authenticated is the SamplePrincipal + userPrincipal = new SamplePrincipal(username); + if (!subject.getPrincipals().contains(userPrincipal)) + subject.getPrincipals().add(userPrincipal); + + if (debug) { + System.out.println("\t\t[SampleLoginModule] " + + "added SamplePrincipal to Subject"); + } + + // in any case, clean out state + username = null; + for (int i = 0; i < password.length; i++) + password[i] = ' '; + password = null; + + commitSucceeded = true; + return true; + } + } + + /** + *

    This method is called if the LoginContext's + * overall authentication failed. + * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules + * did not succeed). + * + *

    If this LoginModule's own authentication attempt + * succeeded (checked by retrieving the private state saved by the + * login and commit methods), + * then this method cleans up any state that was originally saved. + * + *

    + * + * @exception LoginException if the abort fails. + * + * @return false if this LoginModule's own login and/or commit attempts + * failed, and true otherwise. + */ + public boolean abort() throws LoginException { + if (succeeded == false) { + return false; + } else if (succeeded == true && commitSucceeded == false) { + // login succeeded but overall authentication failed + succeeded = false; + username = null; + if (password != null) { + for (int i = 0; i < password.length; i++) + password[i] = ' '; + password = null; + } + userPrincipal = null; + } else { + // overall authentication succeeded and commit succeeded, + // but someone else's commit failed + logout(); + } + return true; + } + + /** + * Logout the user. + * + *

    This method removes the SamplePrincipal + * that was added by the commit method. + * + *

    + * + * @exception LoginException if the logout fails. + * + * @return true in all cases since this LoginModule + * should not be ignored. + */ + public boolean logout() throws LoginException { + + subject.getPrincipals().remove(userPrincipal); + succeeded = false; + succeeded = commitSucceeded; + username = null; + if (password != null) { + for (int i = 0; i < password.length; i++) + password[i] = ' '; + password = null; + } + userPrincipal = null; + return true; + } +} \ No newline at end of file diff --git a/security/TPNote/Notes+Examples/revision/revision/tp2/partie3/sample/principal/SamplePrincipal.java b/security/TPNote/Notes+Examples/revision/revision/tp2/partie3/sample/principal/SamplePrincipal.java new file mode 100644 index 0000000..29621e7 --- /dev/null +++ b/security/TPNote/Notes+Examples/revision/revision/tp2/partie3/sample/principal/SamplePrincipal.java @@ -0,0 +1,144 @@ +/* + * + * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * -Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * -Redistribution in binary form must reproduct the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Oracle nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any + * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY + * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY + * DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT OF OR + * RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR + * ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE + * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, + * SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER + * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF + * THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that Software is not designed, licensed or + * intended for use in the design, construction, operation or + * maintenance of any nuclear facility. + */ + +package sample.principal; + +import java.security.Principal; + +/** + *

    This class implements the Principal interface + * and represents a Sample user. + * + *

    Principals such as this SamplePrincipal + * may be associated with a particular Subject + * to augment that Subject with an additional + * identity. Refer to the Subject class for more information + * on how to achieve this. Authorization decisions can then be based upon + * the Principals associated with a Subject. + * + * @see java.security.Principal + * @see javax.security.auth.Subject + */ +public class SamplePrincipal implements Principal, java.io.Serializable { + + /** + * @serial + */ + private String name; + + /** + * Create a SamplePrincipal with a Sample username. + * + *

    + * + * @param name the Sample username for this user. + * + * @exception NullPointerException if the name + * is null. + */ + public SamplePrincipal(String name) { + if (name == null) + throw new NullPointerException("illegal null input"); + + this.name = name; + } + + /** + * Return the Sample username for this SamplePrincipal. + * + *

    + * + * @return the Sample username for this SamplePrincipal + */ + public String getName() { + return name; + } + + /** + * Return a string representation of this SamplePrincipal. + * + *

    + * + * @return a string representation of this SamplePrincipal. + */ + public String toString() { + return("SamplePrincipal: " + name); + } + + /** + * Compares the specified Object with this SamplePrincipal + * for equality. Returns true if the given object is also a + * SamplePrincipal and the two SamplePrincipals + * have the same username. + * + *

    + * + * @param o Object to be compared for equality with this + * SamplePrincipal. + * + * @return true if the specified Object is equal equal to this + * SamplePrincipal. + */ + public boolean equals(Object o) { + if (o == null) + return false; + + if (this == o) + return true; + + if (!(o instanceof SamplePrincipal)) + return false; + SamplePrincipal that = (SamplePrincipal)o; + + if (this.getName().equals(that.getName())) + return true; + return false; + } + + /** + * Return a hash code for this SamplePrincipal. + * + *

    + * + * @return a hash code for this SamplePrincipal. + */ + public int hashCode() { + return name.hashCode(); + } +} \ No newline at end of file diff --git a/security/TPNote/Notes+Examples/signatureAvecCertificat.sh b/security/TPNote/Notes+Examples/signatureAvecCertificat.sh new file mode 100755 index 0000000..ca5b9ab --- /dev/null +++ b/security/TPNote/Notes+Examples/signatureAvecCertificat.sh @@ -0,0 +1,112 @@ +#!/bin/bash + +# Reset +rm -rf ./CA +rm ./client/certificat_request.csr \ + ./client/certificat_signed.cer \ + ./client/certificat.cer \ + ./client/keystore.jks \ + ./client/Source_Signed.jar + +########################################## + +# Création des dossiers CA et client s'ils n'existent pas déjà +mkdir -p CA client + +# Génération de la clé privée de la CA +openssl genrsa -out CA/ca.key 2048 +echo "[CA] - génération de la clé privée : OK" + +# Génération du certificat auto-signé de la CA +openssl req -x509 -new -nodes \ + -key CA/ca.key -sha256 -days 365 \ + -out CA/ca.crt \ + -subj "/CN=SimulatedCA/O=MyCA/C=FR" +echo "[CA] - génération du certificat auto-signé : OK" + +# Génération du keystore du client +keytool -genkeypair \ + -alias KeyAlias \ + -keyalg RSA \ + -keysize 2048 \ + -keystore client/keystore.jks \ + -validity 365 \ + -dname "CN=ClientName, OU=ClientUnit, O=ClientOrg, L=ClientCity, S=ClientState, C=FR" \ + -storepass changeit \ + -keypass changeit +echo "[Client] - Génération du keystore : OK" + +# Génération de la demande de certificat (CSR) pour le client +keytool -certreq \ + -alias KeyAlias \ + -keystore client/keystore.jks \ + -file client/certificat_request.csr \ + -storepass changeit +echo "[Client] - Génération de la demande de certification : OK" + +# La CA signe la demande de certificat du client +openssl x509 -req \ + -in client/certificat_request.csr \ + -CA CA/ca.crt -CAkey CA/ca.key -CAcreateserial \ + -out client/certificat_signed.cer -days 365 -sha256 +echo "[CA] - Signature de la demande de certificat : OK" + +# Importation du certificat de la CA dans le keystore du client +keytool -import \ + -trustcacerts \ + -alias SimulatedCA \ + -file CA/ca.crt \ + -keystore client/keystore.jks \ + -noprompt \ + -storepass changeit +echo "[Client] - Import du certificat du CA : OK" + +# Importation du certificat signé dans le keystore du client +keytool -import \ + -alias KeyAlias \ + -keystore client/keystore.jks \ + -file client/certificat_signed.cer \ + -noprompt \ + -storepass changeit +echo "[Client] - Import du certificat signé : OK" + +# Exportation du certificat signé pour distribution +keytool -export \ + -alias KeyAlias \ + -keystore client/keystore.jks \ + -file client/certificat.cer \ + -storepass changeit +echo "[Client] - Export du certificat signé : OK" + +########################################## + +cd ./client/ + +# Compile notre fichier java +javac ./Source.java +echo "[Client] - Compilation du .java : OK" + +# Créer un fichier MANIFEST.MF avec l'attribut Main-Class +echo "Main-Class: Source" > ./MANIFEST.MF + +# Créé le fichier Jar non signé +jar cmf ./MANIFEST.MF ./Source.jar ./Source.class +echo "[Client] - Creation du fichier .jar : OK" + +# Convertis en fichier jar signé +jarsigner -keystore ./keystore.jks \ + -storepass changeit \ + -signedjar ./Source_Signed.jar ./Source.jar KeyAlias +echo "[Client] - Creation du fichier .jar signé : OK" + +# Supprime les artéfacts +rm ./Source.class ./Source.jar ./MANIFEST.MF + +# On peut vérifier que notre certificat est bien valide +jarsigner -verify ./Source_Signed.jar +echo "[Client] - Vérification du certificat : OK" + +cd .. + +# Executer le jar signé +java -jar ./client/Source_Signed.jar diff --git a/security/TPNote/Notes+Examples/signatureSansCertificat.sh b/security/TPNote/Notes+Examples/signatureSansCertificat.sh new file mode 100755 index 0000000..8f99cbd --- /dev/null +++ b/security/TPNote/Notes+Examples/signatureSansCertificat.sh @@ -0,0 +1,29 @@ +# Reset +rm ./keystore.jks ./Source_Signed.jar + +# Génère un keystore +keytool -genkeypair \ + -alias SourceKeyAlias \ + -keyalg RSA \ + -keysize 2048 \ + -keystore keystore.jks \ + -validity 365 + +# Compilation +javac ./Source.java + +# Créer un fichier MANIFEST.MF avec l'attribut Main-Class +echo "Main-Class: Source" > MANIFEST.MF + +# Crée le fichier JAR non signé avec le MANIFEST.MF modifié +jar cmf MANIFEST.MF Source.jar Source.class + +# Convertir en fichier JAR signé +jarsigner -keystore keystore.jks \ + -signedjar Source_Signed.jar Source.jar SourceKeyAlias + +# Supprime les artéfacts +rm ./Source.class ./Source.jar MANIFEST.MF + +# Essaye d'exécuter ton fichier JAR signé +java -jar Source_Signed.jar \ No newline at end of file