Impossible de trouver un chemin de certification valide vers la cible demandée - erreur même après l'importation du certificat


206

J'ai un client Java essayant d'accéder à un serveur avec un certificat auto-signé.

Lorsque j'essaie de publier sur le serveur, j'obtiens l'erreur suivante:

impossible de trouver un chemin de certification valide vers la cible demandée

Après avoir fait quelques recherches sur la question, j'ai ensuite fait ce qui suit.

  1. J'ai enregistré le nom de domaine de mes serveurs dans un root.cerfichier.
  2. Dans le JRE de mon serveur Glassfish, j'ai exécuté ceci:
    keytool -import -alias example -keystore cacerts -file root.cer
  3. Pour vérifier que le certificat a bien été ajouté à mon cacert, j'ai fait ceci:
    keytool -list -v -keystore cacerts
    je peux voir que le certificat est présent.
  4. J'ai ensuite redémarré Glassfish et retiré le «poste».

Je reçois toujours la même erreur.

J'ai l'impression que c'est parce que mon Glassfish ne lit pas réellement le fichier cacert que j'ai modifié mais peut-être un autre.

Avez-vous eu ce problème et pouvez-vous me pousser dans la bonne direction?


1
Juste pour clarifier "J'ai un client Java qui essaie d'accéder à un serveur avec un certificat auto-signé.": Vous parlez d'utiliser des certificats clients qui sont auto-signés, n'est-ce pas? Existe-t-il une configuration spécifique pour les paramètres de votre connecteur sur Glassfish (paramètres Trust Store, en particulier)?
Bruno

"J'ai un client Java qui essaie d'accéder à un serveur avec un certificat auto-signé.": Vous parlez d'utiliser des certificats clients qui sont auto-signés, n'est-ce pas? - Oui.
TheCoder

1
J'ai trouvé 2 paramètres dans Glassfish JVM: -Djavax.net.ssl.keyStore = $ {com.sun.aas.instanceRoot} /config/keystore.jks et -Djavax.net.ssl.trustStore = $ {com.sun. aas.instanceRoot} /config/cacerts.jks. Je dois maintenant ajouter par cert à l'un d'eux. Pouvez-vous confirmer qu'il s'agit du magasin de clés auquel je l'ajoute?
TheCoder

4
Sur le serveur, le magasin de clés correspond au certificat du serveur et à sa clé privée (le magasin de clés correspond à ce qui "appartient" au correspondant local). Le fichier de clés certifiées est destiné aux certificats utilisés pour vérifier la confiance dans la partie distante. Vous devez ajouter le certificat client à votre magasin d'approbations de serveur. (Voir ce aussi, bien que Glassfish ne semble pas être en utilisant l'emplacement par défaut de JRE.)
Bruno

Cela a fonctionné Bruno. Je l'ai ajouté à mon truststore Glassfish. Merci beaucoup pour votre aide. Toi aussi Dirk.
TheCoder

Réponses:


155

Malheureusement - cela pourrait être beaucoup de choses - et beaucoup de serveurs d'applications et d'autres «wrappers» java sont enclins à jouer avec les propriétés et leur «propre» prise sur les trousseaux et quoi d'autre. Il peut donc s'agir de quelque chose de totalement différent.

À court de fermes - j'essaierais:

java -Djavax.net.debug=all -Djavax.net.ssl.trustStore=trustStore ...

pour voir si ça aide. Au lieu de «tout», vous pouvez également le définir sur «ssl», gestionnaire de clés et gestionnaire de confiance - ce qui peut vous aider dans votre cas. Le définir sur «aide» affichera quelque chose comme ci-dessous sur la plupart des plateformes.

Quoi qu'il en soit - assurez-vous de bien comprendre la différence entre le magasin de clés (dans lequel vous avez la clé privée et le certificat avec lequel vous prouvez votre propre identité) et le magasin de confiance (qui détermine à qui vous faites confiance) - et le fait que votre propre identité a une «chaîne» de confiance à la racine - qui est distincte de toute chaîne à une racine dont vous avez besoin pour comprendre «à qui» vous faites confiance.

all            turn on all debugging
ssl            turn on ssl debugging

The   following can be used with ssl:
    record       enable per-record tracing
    handshake    print each handshake message
    keygen       print key generation data
    session      print session activity
    defaultctx   print default SSL initialization
    sslctx       print SSLContext tracing
    sessioncache print session cache tracing
    keymanager   print key manager tracing
    trustmanager print trust manager tracing
    pluggability print pluggability tracing

    handshake debugging can be widened with:
    data         hex dump of each handshake message
    verbose      verbose handshake message printing

    record debugging can be widened with:
    plaintext    hex dump of record plaintext
    packet       print raw SSL/TLS packets

Source: # Voir http://download.oracle.com/javase/1.5.0/docs/guide/security/jsse/JSSERefGuide.html#Debug


6
Merci beaucoup! -Djavax.net.ssl.trustStore = / location_of / trustStore a résolu mon problème et les informations de débogage étaient également très utiles.
RHE

5
java -Djavax.net.debug = all -Djavax.net.ssl.trustStore = trustStore ... donne l'erreur ci-dessous: Erreur: impossible de trouver ou de charger la classe principale ...
rohith

1
Bien sûr, vous devrez peut-être également spécifier le mot de passe du truststore avec -Djavax.net.ssl.trustStorePassword = changeit
user1754036

18

Voici la solution, suivez le lien ci-dessous étape par étape:

http://www.mkyong.com/webservices/jax-ws/suncertpathbuilderexception-unable-to-find-valid-certification-path-to-requested-target/

FICHIER JAVA: absent du blog

/*
 * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */



import java.io.*;
import java.net.URL;

import java.security.*;
import java.security.cert.*;

import javax.net.ssl.*;

public class InstallCert {

    public static void main(String[] args) throws Exception {
    String host;
    int port;
    char[] passphrase;
    if ((args.length == 1) || (args.length == 2)) {
        String[] c = args[0].split(":");
        host = c[0];
        port = (c.length == 1) ? 443 : Integer.parseInt(c[1]);
        String p = (args.length == 1) ? "changeit" : args[1];
        passphrase = p.toCharArray();
    } else {
        System.out.println("Usage: java InstallCert <host>[:port] [passphrase]");
        return;
    }

    File file = new File("jssecacerts");
    if (file.isFile() == false) {
        char SEP = File.separatorChar;
        File dir = new File(System.getProperty("java.home") + SEP
            + "lib" + SEP + "security");
        file = new File(dir, "jssecacerts");
        if (file.isFile() == false) {
        file = new File(dir, "cacerts");
        }
    }
    System.out.println("Loading KeyStore " + file + "...");
    InputStream in = new FileInputStream(file);
    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
    ks.load(in, passphrase);
    in.close();

    SSLContext context = SSLContext.getInstance("TLS");
    TrustManagerFactory tmf =
        TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmf.init(ks);
    X509TrustManager defaultTrustManager = (X509TrustManager)tmf.getTrustManagers()[0];
    SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
    context.init(null, new TrustManager[] {tm}, null);
    SSLSocketFactory factory = context.getSocketFactory();

    System.out.println("Opening connection to " + host + ":" + port + "...");
    SSLSocket socket = (SSLSocket)factory.createSocket(host, port);
    socket.setSoTimeout(10000);
    try {
        System.out.println("Starting SSL handshake...");
        socket.startHandshake();
        socket.close();
        System.out.println();
        System.out.println("No errors, certificate is already trusted");
    } catch (SSLException e) {
        System.out.println();
        e.printStackTrace(System.out);
    }

    X509Certificate[] chain = tm.chain;
    if (chain == null) {
        System.out.println("Could not obtain server certificate chain");
        return;
    }

    BufferedReader reader =
        new BufferedReader(new InputStreamReader(System.in));

    System.out.println();
    System.out.println("Server sent " + chain.length + " certificate(s):");
    System.out.println();
    MessageDigest sha1 = MessageDigest.getInstance("SHA1");
    MessageDigest md5 = MessageDigest.getInstance("MD5");
    for (int i = 0; i < chain.length; i++) {
        X509Certificate cert = chain[i];
        System.out.println
            (" " + (i + 1) + " Subject " + cert.getSubjectDN());
        System.out.println("   Issuer  " + cert.getIssuerDN());
        sha1.update(cert.getEncoded());
        System.out.println("   sha1    " + toHexString(sha1.digest()));
        md5.update(cert.getEncoded());
        System.out.println("   md5     " + toHexString(md5.digest()));
        System.out.println();
    }

    System.out.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]");
    String line = reader.readLine().trim();
    int k;
    try {
        k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1;
    } catch (NumberFormatException e) {
        System.out.println("KeyStore not changed");
        return;
    }

    X509Certificate cert = chain[k];
    String alias = host + "-" + (k + 1);
    ks.setCertificateEntry(alias, cert);

    OutputStream out = new FileOutputStream("jssecacerts");
    ks.store(out, passphrase);
    out.close();

    System.out.println();
    System.out.println(cert);
    System.out.println();
    System.out.println
        ("Added certificate to keystore 'jssecacerts' using alias '"
        + alias + "'");
    }

    private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();

    private static String toHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder(bytes.length * 3);
        for (int b : bytes) {
            b &= 0xff;
            sb.append(HEXDIGITS[b >> 4]);
            sb.append(HEXDIGITS[b & 15]);
            sb.append(' ');
        }
        return sb.toString();
    }

    private static class SavingTrustManager implements X509TrustManager {

    private final X509TrustManager tm;
    private X509Certificate[] chain;

    SavingTrustManager(X509TrustManager tm) {
        this.tm = tm;
    }

    public X509Certificate[] getAcceptedIssuers() {
        throw new UnsupportedOperationException();
    }

    public void checkClientTrusted(X509Certificate[] chain, String authType)
        throws CertificateException {
        throw new UnsupportedOperationException();
    }

    public void checkServerTrusted(X509Certificate[] chain, String authType)
        throws CertificateException {
        this.chain = chain;
        tm.checkServerTrusted(chain, authType);
    }
    }

}

3
Cette solution a fonctionné pour moi, mais elle a besoin d'un petit changement dans la classe privée SavingTrustManager:public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0];}
Richard

1
@ Richard, @ Paul, @ user6258309 J'ai eu l'erreur Exception dans le thread "principal" java.net.SocketTimeoutException: lecture expirée sur java.net.SocketInputStream.socketRead0 (méthode native) sur java.net.SocketInputStream.socketRead (source inconnue) ) Comment puis-je résoudre ce problème
Renjith Krishnan

5
Cette «so; lution» est radicalement précaire. Ne pas utiliser.
Marquis de Lorne

9
Cette réponse est principalement du code. Cela n'explique pas pourquoi ou pourquoi cela ne fonctionne pas.

13

Vous devez configurer les propriétés système JSSE, en particulier pointer vers le magasin de certificats client.

Via la ligne de commande:

java -Djavax.net.ssl.trustStore=truststores/client.ts com.progress.Client

ou via du code Java:

import java.util.Properties;
    ...
    Properties systemProps = System.getProperties();
    systemProps.put("javax.net.ssl.keyStorePassword","passwordForKeystore");
    systemProps.put("javax.net.ssl.keyStore","pathToKeystore.ks");
    systemProps.put("javax.net.ssl.trustStore", "pathToTruststore.ts");
    systemProps.put("javax.net.ssl.trustStorePassword","passwordForTrustStore");
    System.setProperties(systemProps);
    ...

Pour plus d'informations, reportez-vous aux détails sur le site RedHat .


Nous avons eu le même problème avec Spring Boot, les microservices Spring Cloud et un certificat SSL auto-signé. J'ai pu définir keyStore et keyStorePassword dans application.properties et le faire fonctionner comme ça dès la sortie de la boîte, mais je n'ai pas réussi à faire de même avec trustStore et trustStorePassword. Cette réponse a fonctionné pour moi pour Trust Store.
Mate Šimović

7

(republication de mon autre réponse )
Utilisez l' utilitaire cli keytool de distribution de logiciels java pour l' importation (et la confiance! ) les certificats nécessaires

Échantillon:

  1. Du cli change dir en jre \ bin

  2. Vérifier le fichier de clés (fichier trouvé dans le répertoire jre \ bin)
    keytool -list -keystore .. \ lib \ security \ cacerts Le
    mot de passe est changé

  3. Téléchargez et enregistrez tous les certificats en chaîne à partir du serveur requis.

  4. Ajoutez des certificats (avant de supprimer l'attribut "lecture seule" du fichier ".. \ lib \ security \ cacerts"), exécutez: keytool -alias REPLACE_TO_ANY_UNIQ_NAME -import -keystore .. \ lib \ security \ cacerts -file "r: \ root.crt "

accidentellement, j'ai trouvé une astuce aussi simple. D'autres solutions nécessitent l'utilisation de InstallCert.Java et JDK

source: http://www.java-samples.com/showtutorial.php?tutorialid=210


6

J'ai eu le même problème avec sbt .
Il a essayé de récupérer les dépendances de repo1.maven.org sur ssl
mais a déclaré qu'il "était incapable de trouver un chemin de certification valide vers l'URL cible demandée".
J'ai donc suivi ce post et je n'ai toujours pas vérifié la connexion.
J'ai donc lu à ce sujet et j'ai constaté que le certificat racine ne suffisait pas, comme l'a suggéré la publication, donc -
la chose qui a fonctionné pour moi était l'importation des certificats CA intermédiaires dans le magasin de clés .
J'ai en fait ajouté tous les certificats de la chaîne et cela a fonctionné comme un charme.


4

Solution lors de la migration de JDK 8 vers JDK 10

JDK 10

root@c339504909345:/opt/jdk-minimal/jre/lib/security #  keytool -cacerts -list
Enter keystore password:
Keystore type: JKS
Keystore provider: SUN

Your keystore contains 80 entries

JDK 8

root@c39596768075:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/security/cacerts #  keytool -cacerts -list
Enter keystore password:
Keystore type: JKS
Keystore provider: SUN

Your keystore contains 151 entries

Étapes à suivre

  • J'ai supprimé le certificat JDK 10 et l'ai remplacé par le JDK 8
  • Puisque je crée des images Docker, je pourrais le faire rapidement en utilisant des versions multi-étapes
    • Je construis un JRE minimal en utilisant jlinkcomme/opt/jdk/bin/jlink \ --module-path /opt/jdk/jmods...

Alors, voici les différents chemins et la séquence des commandes ...

# Java 8
COPY --from=marcellodesales-springboot-builder-jdk8 /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/security/cacerts /etc/ssl/certs/java/cacerts

# Java 10
RUN rm -f /opt/jdk-minimal/jre/lib/security/cacerts
RUN ln -s /etc/ssl/certs/java/cacerts /opt/jdk-minimal/jre/lib/security/cacerts

2

Je travaille sur un didacticiel pour les services Web REST sur www.udemy.com (REST Java Web Services). L'exemple du didacticiel disait que pour avoir SSL, nous devons avoir un dossier appelé "trust_store" dans mon projet "client" d'éclipse qui devrait contenir un fichier "magasin de clés" (nous avions un projet "client" pour appeler le service et projet "service" qui contenait le service Web REST - 2 projets dans le même espace de travail éclipse, l'un le client, l'autre le service). Pour simplifier les choses, ils ont dit de copier "keystore.jks" à partir du serveur d'application glassfish (glassfish \ domain \ domain1 \ config \ keystore.jks) que nous utilisons et de le placer dans ce dossier "trust_store" dans lequel ils m'ont fait créer le projet client. Cela semble logique: les certificats auto-signés sur le serveur » s key_store correspondrait aux certificats du client trust_store. Maintenant, ce faisant, je recevais l'erreur que le message d'origine mentionne. J'ai googlé ceci et lu que l'erreur est due au fichier "keystore.jks" sur le client ne contenant pas de certificat approuvé / signé, que le certificat qu'il trouve est auto-signé.

Pour que les choses soient claires, permettez-moi de dire que si je comprends bien, le fichier "keystore.jks" contient des certificats auto-signés et le fichier "cacerts.jks" contient des certificats CA (signés par le CA). Le "keystore.jks" est le "keystore" et le "cacerts.jks" est le "trust store". Comme "Bruno", un commentateur, l'a dit plus haut, "keystore.jks" est local et "cacerts.jks" est destiné aux clients distants.

Donc, je me suis dit, hé, glassfish a aussi le fichier "cacerts.jks", qui est le fichier trust_store de glassfish. cacerts.jsk est censé contenir des certificats CA. Et apparemment, j'ai besoin que mon dossier trust_store contienne un fichier de stockage de clés contenant au moins un certificat CA. J'ai donc essayé de placer le fichier "cacerts.jks" dans le dossier "trust_store" que j'avais créé, sur mon projet client, et de modifier les propriétés de la machine virtuelle pour pointer sur "cacerts.jks" au lieu de "keystore.jks". Cela s'est débarrassé de l'erreur. Je suppose que tout ce dont il avait besoin était d'un certificat CA pour fonctionner.

Cela peut ne pas être idéal pour la production, ni même pour le développement au-delà du simple fait de faire fonctionner quelque chose. Par exemple, vous pourriez probablement utiliser la commande "keytool" pour ajouter des certificats CA au fichier "keystore.jks" dans le client. Mais de toute façon, j'espère que cela réduit au moins les scénarios possibles qui pourraient se produire ici pour provoquer l'erreur.

AUSSI: mon approche semblait utile pour le client (certificat serveur ajouté au client trust_store), il semble que les commentaires ci-dessus pour résoudre le message d'origine soient utiles pour le serveur (certificat client ajouté au serveur trust_store). À votre santé.

Configuration du projet Eclipse:

  • MyClientProject
  • src
  • tester
  • Bibliothèque système JRE
  • ...
  • trust_store
    --- cacerts.jks --- keystore.jks

Extrait du fichier MyClientProject.java:

static {
  // Setup the trustStore location and password
  System.setProperty("javax.net.ssl.trustStore","trust_store/cacerts.jks");
  // comment out below line
  System.setProperty("javax.net.ssl.trustStore","trust_store/keystore.jks");
  System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
  //System.setProperty("javax.net.debug", "all");

  // for localhost testing only
  javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(new javax.net.ssl.HostnameVerifier() {
        public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) {
          return hostname.equals("localhost");
        }

  });
}

1

Mon problème était qu'un courtier de sécurité d'accès au cloud, NetSkope, a été installé sur mon ordinateur portable professionnel via une mise à jour logicielle. Cela modifiait la chaîne de certificats et je ne pouvais toujours pas me connecter au serveur via mon client java après avoir importé la chaîne entière dans mon magasin de clés cacerts. J'ai désactivé NetSkope et j'ai réussi à me connecter.


1

Dans mon cas, je faisais face au problème parce que dans mon processus tomcat, un magasin de clés spécifique a été donné en utilisant

-Djavax.net.ssl.trustStore=/pathtosomeselfsignedstore/truststore.jks

Alors que j'importais le certificat dans le cacert de JRE / lib / security et que les changements ne se reflétaient pas. Ensuite, j'ai fait la commande ci-dessous où /tmp/cert1.test contient le certificat du serveur cible

keytool -import -trustcacerts -keystore /pathtosomeselfsignedstore/truststore.jks -storepass password123 -noprompt -alias rapidssl-myserver -file /tmp/cert1.test

Nous pouvons vérifier si l'importation du certificat a réussi

keytool -list -v -keystore /pathtosomeselfsignedstore/truststore.jks

et voyez si votre serveur de taget est trouvé contre l'alias rapidssl-myserver


0

Vérifiez si le fichier $JAVA_HOME/lib/security/cacertsexiste! Dans mon cas, ce n'était pas un fichier mais un lien vers/etc/ssl/certs/java/cacerts et c'était également un lien vers lui-même (QUOI ???) donc à cause de cela JVM ne peut pas trouver le fichier.

Solution: copiez le vrai fichier cacerts ( vous pouvez le faire à partir d'un autre JDK ) dans le /etc/ssl/certs/java/répertoire et cela résoudra votre problème :)


en effet, JDK maintient un lien et peut-être pour des raisons de compatibilité avec les anciennes API, SDK ... J'ai réussi à faire de même ... Je passe de JDK 8 à JDK 10 et j'utilise Docker donc j'avais juste besoin de copier les cacerts d'un image à une autre ... J'ai créé le lien et de la même manière exacte ...rm -f /opt/jdk-minimal/jre/lib/security/cacerts ; ln -s /etc/ssl/certs/java/cacerts /opt/jdk-minimal/jre/lib/security/cacerts
Marcello de Sales

-9

Disons si vous utilisez des variables de chemin de classe comme $ {JAVA_HOME} dans pom.xml.

<target>
                    <property name="compile_classpath" refid="maven.compile.classpath"/>
                    <property name="runtime_classpath" refid="maven.runtime.classpath"/>
                    <property name="test_classpath" refid="maven.test.classpath"/>
                    <property name="plugin_classpath" refid="maven.plugin.classpath"/>
                    <property name="jaxb-api.jar" value="${maven.dependency.javax.xml.bind.jaxb-api.jar.path}"/>
                    <property name="project_home" value="${PROJECT_HOME}"/>
                    <property name="java_home" value="${JAVA_HOME}"/>
                    <property name="ant_home" value="${ANT_HOME}"/>
                    <property name="common_home" value="${COMMON_HOME}"/>
                    <property name="JAXP_HOME" value="${common_home}/lib"/>
                    <property name="ejfw_home" value="${PROJECT_HOME}/lib"/>
                    <property name="weblogic_home" value="${WL_HOME}"/>
                    <property name="fw_home" value="${FW_HOME}"/>
                    <property name="env" value="${BUILDENV}"/>
                    <property name="tokenfile" value="${BUILDENV}${BUILDENV_S2S}.properties"/>

Sur les objectifs, ajoutez les variables classpath. c'est-à-dire .., -DANT_HOME, -DJAVA_HOME

clean install -e -DPROJECT_HOME=..... -DANT_HOME=C:\bea1036\modules\org.apache.ant_1.7.1 -DJAVA_HOME=C:\bea1036\jdk160_31

1
Les chemins de classe et les certificats n'ont absolument rien à voir les uns avec les autres.
Marquis de Lorne

1
Je pense que vous avez mal compris la question.
Dawood ibn Kareem
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.