public void exportIntroduction(OwnIdentity identity, OutputStream os) throws TransformerException { Document xmlDoc; synchronized ( mDocumentBuilder) { // TODO: Figure out whether the DocumentBuilder is maybe synchronized // anyway xmlDoc = mDOM.createDocument(null, WebOfTrust.WOT_NAME, null); } // 1.0 does not support all Unicode characters which the String class supports. To prevent us // from having to filter all Strings, we use 1.1 xmlDoc.setXmlVersion("1.1"); Element rootElement = xmlDoc.getDocumentElement(); // We include the WoT version to have an easy way of handling bogus XML which might be created // by bugged versions. rootElement.setAttribute("Version", Long.toString(Version.getRealVersion())); Element introElement = xmlDoc.createElement("IdentityIntroduction"); introElement.setAttribute( "Version", Integer.toString(XML_FORMAT_VERSION)); /* Version of the XML format */ Element identityElement = xmlDoc.createElement("Identity"); // synchronized(mWoT) { // Not necessary according to JavaDoc of identity.getRequestURI() identityElement.setAttribute("URI", identity.getRequestURI().toString()); // } introElement.appendChild(identityElement); rootElement.appendChild(introElement); DOMSource domSource = new DOMSource(xmlDoc); StreamResult resultStream = new StreamResult(os); synchronized ( mSerializer) { // TODO: Figure out whether the Serializer is maybe synchronized anyway mSerializer.transform(domSource, resultStream); } }
/** * Creates an identity from an identity introduction, stores it in the database and returns the * new identity. If the identity already exists, the existing identity is returned. * * <p>You have to synchronize on the WebOfTrust object when using this function! TODO: Remove this * requirement and re-query the parameter OwnIdentity puzzleOwner from the database after we are * synchronized. * * @param xmlInputStream An InputStream which must not return more than {@link * MAX_INTRODUCTION_BYTE_SIZE} bytes. * @throws InvalidParameterException If the XML format is unknown or if the puzzle owner does not * allow introduction anymore. * @throws IOException * @throws SAXException */ public Identity importIntroduction(OwnIdentity puzzleOwner, InputStream xmlInputStream) throws InvalidParameterException, SAXException, IOException { xmlInputStream = new OneBytePerReadInputStream( xmlInputStream); // Workaround for Java bug, see the stream class for explanation // May not be accurate by definition of available(). So the JavaDoc requires the callers to obey // the size limit, this is a double-check. if (xmlInputStream.available() > MAX_INTRODUCTION_BYTE_SIZE) throw new IllegalArgumentException( "XML contains too many bytes: " + xmlInputStream.available()); FreenetURI identityURI; Identity newIdentity; Document xmlDoc; synchronized ( mDocumentBuilder) { // TODO: Figure out whether the DocumentBuilder is maybe synchronized // anyway xmlDoc = mDocumentBuilder.parse(xmlInputStream); } Element introductionElement = (Element) xmlDoc.getElementsByTagName("IdentityIntroduction").item(0); if (Integer.parseInt(introductionElement.getAttribute("Version")) > XML_FORMAT_VERSION) throw new InvalidParameterException( "Version " + introductionElement.getAttribute("Version") + " > " + XML_FORMAT_VERSION); Element identityElement = (Element) introductionElement.getElementsByTagName("Identity").item(0); identityURI = new FreenetURI(identityElement.getAttribute("URI")); final IdentityFetcher identityFetcher = mWoT.getIdentityFetcher(); synchronized (mWoT) { synchronized (identityFetcher) { if (!puzzleOwner.hasContext(IntroductionPuzzle.INTRODUCTION_CONTEXT)) throw new InvalidParameterException( "Trying to import an identity identroduction for an own identity which does not allow introduction."); synchronized (Persistent.transactionLock(mDB)) { try { try { newIdentity = mWoT.getIdentityByURI(identityURI); if (logMINOR) Logger.minor( this, "Imported introduction for an already existing identity: " + newIdentity); } catch (UnknownIdentityException e) { newIdentity = new Identity(mWoT, identityURI, null, false); // We do NOT call setEdition(): An attacker might solve puzzles pretending to be // someone else and publish bogus edition numbers for // that identity by that. The identity constructor only takes the edition number as // edition hint, this is the proper behavior. // TODO: As soon as we have code for signing XML with an identity SSK we could sign // the introduction XML and therefore prevent that // attack. // newIdentity.setEdition(identityURI.getEdition()); newIdentity.storeWithoutCommit(); if (logMINOR) Logger.minor(this, "Imported introduction for an unknown identity: " + newIdentity); } try { mWoT.getTrust(puzzleOwner, newIdentity); /* Double check ... */ if (logMINOR) Logger.minor(this, "The identity is already trusted."); } catch (NotTrustedException ex) { // 0 trust will not allow the import of other new identities for the new identity // because the trust list import code will only create // new identities if the score of an identity is > 0, not if it is equal to 0. mWoT.setTrustWithoutCommit( puzzleOwner, newIdentity, (byte) 0, "Trust received by solving a captcha."); } // setTrustWithoutCommit() does this for us. // identityFetcher.storeStartFetchCommandWithoutCommit(newIdentity.getID()); newIdentity.checkedCommit(this); } catch (RuntimeException error) { Persistent.checkedRollbackAndThrow(mDB, this, error); // Satisfy the compiler - without this the return at the end of the function would // complain about the uninitialized newIdentity variable throw error; } } } } return newIdentity; }
public void exportOwnIdentity(OwnIdentity identity, OutputStream os) throws TransformerException { Document xmlDoc; synchronized ( mDocumentBuilder) { // TODO: Figure out whether the DocumentBuilder is maybe synchronized // anyway xmlDoc = mDOM.createDocument(null, WebOfTrust.WOT_NAME, null); } // 1.0 does not support all Unicode characters which the String class supports. To prevent us // from having to filter all Strings, we use 1.1 xmlDoc.setXmlVersion("1.1"); Element rootElement = xmlDoc.getDocumentElement(); // We include the WoT version to have an easy way of handling bogus XML which might be created // by bugged versions. rootElement.setAttribute("Version", Long.toString(Version.getRealVersion())); /* Create the identity Element */ Element identityElement = xmlDoc.createElement("Identity"); identityElement.setAttribute( "Version", Integer.toString(XML_FORMAT_VERSION)); /* Version of the XML format */ synchronized (mWoT) { identityElement.setAttribute("Name", identity.getNickname()); identityElement.setAttribute( "PublishesTrustList", Boolean.toString(identity.doesPublishTrustList())); /* Create the context Elements */ for (String context : identity.getContexts()) { Element contextElement = xmlDoc.createElement("Context"); contextElement.setAttribute("Name", context); identityElement.appendChild(contextElement); } /* Create the property Elements */ for (Entry<String, String> property : identity.getProperties().entrySet()) { Element propertyElement = xmlDoc.createElement("Property"); propertyElement.setAttribute("Name", property.getKey()); propertyElement.setAttribute("Value", property.getValue()); identityElement.appendChild(propertyElement); } /* Create the trust list Element and its trust Elements */ if (identity.doesPublishTrustList()) { Element trustListElement = xmlDoc.createElement("TrustList"); int trustCount = 0; for (Trust trust : mWoT.getGivenTrustsSortedDescendingByLastSeen(identity)) { if (++trustCount > MAX_IDENTITY_XML_TRUSTEE_AMOUNT) { Logger.normal( this, "Amount of trustees exceeded " + MAX_IDENTITY_XML_TRUSTEE_AMOUNT + ", not adding any more to trust list of " + identity); break; } /* We should make very sure that we do not reveal the other own identity's */ if (trust.getTruster() != identity) throw new RuntimeException( "Error in WoT: It is trying to export trust values of someone else in the trust list " + "of " + identity + ": Trust value from " + trust.getTruster() + ""); Element trustElement = xmlDoc.createElement("Trust"); trustElement.setAttribute("Identity", trust.getTrustee().getRequestURI().toString()); trustElement.setAttribute("Value", Byte.toString(trust.getValue())); trustElement.setAttribute("Comment", trust.getComment()); trustListElement.appendChild(trustElement); } identityElement.appendChild(trustListElement); } } rootElement.appendChild(identityElement); DOMSource domSource = new DOMSource(xmlDoc); StreamResult resultStream = new StreamResult(os); synchronized ( mSerializer) { // TODO: Figure out whether the Serializer is maybe synchronized anyway mSerializer.transform(domSource, resultStream); } }