package thaw.plugins.webOfTrust; import thaw.core.Logger; import thaw.fcp.FreenetURIHelper; import thaw.plugins.Hsqldb; import thaw.plugins.signatures.*; import java.io.File; import java.sql.*; import java.util.Iterator; import java.util.Vector; import org.xml.sax.Attributes; import org.xml.sax.SAXException; public class WotIdentity extends Identity implements TrustListParser.TrustListContainer { protected WotIdentity() { } protected WotIdentity(Identity i) { super(i.getDb(), i.getId(), i.getNick(), i.getPublicKey(), i.getPrivateKey(), i.isDup(), i.getTrustLevel()); } public int getTrustLevel() { int t; if ( (t = getUserTrustLevel()) != 0) return t; return getWotTrustLevel(); } public int getWotTrustLevel() { /* TODO */ return 0; } public int getUserTrustLevel() { return super.getTrustLevel(); } public String getUserTrustLevelStr() { return super.getTrustLevelStr(); } /** * @return true if lastUpdate in the db is == NULL */ public boolean currentTrustListHasAlreadyBeenDownloaded() { try { synchronized(getDb().dbLock) { PreparedStatement st = getDb().getConnection().prepareStatement("SELECT lastDownload FROM wotKeys WHERE sigId = ? LIMIT 1"); st.setInt(1, getId()); ResultSet set = st.executeQuery(); boolean b = false; if (set.next()) { b = (set.getTimestamp("lastDownload") != null); } st.close(); return b; } } catch(SQLException e) { Logger.error(this, "Error while checking if we already have the trust list of the identity '"+toString()+"'"); e.printStackTrace(); } return false; } /** * @param db * @return null if unknown */ public static WotIdentity getIdentity(Hsqldb db, String wotPublicKey) { try { synchronized(db.dbLock) { /* TODO : Optimize ! sluggard ! */ PreparedStatement st = db.getConnection().prepareStatement("SELECT sigId FROM wotKeys WHERE LOWER(publicKey) LIKE ? LIMIT 1"); st.setString(1, FreenetURIHelper.getComparablePart(wotPublicKey)+"%"); ResultSet set = st.executeQuery(); if (!set.next()) { st.close(); return null; } WotIdentity wi = new WotIdentity(Identity.getIdentity(db, set.getInt("sigId"))); st.close(); return wi; } } catch(SQLException e) { Logger.error(new WotIdentity(), "Error while getting the identity corresponding to a wot public key: "+e.toString()); e.printStackTrace(); } return null; } /** * TODO : Check and update uploadDate * @author jflesch */ protected class TrustListSecurityHandler extends TrustListParser.TrustListHandler implements TrustListParser.TrustListContainer { private TrustListSecurityHandler() { super(null /* java doesn't accept 'this' as argument here */); setTrustListContainer(this); } private boolean trustListOwnerTag = false; private boolean nickTag = false; private boolean publicKeyTag = false; private String nick = null; private String publicKey = null; public void startElement(String nameSpaceURI, String localName, String rawName, Attributes attrs) throws SAXException { if (rawName == null) { rawName = localName; } if (rawName == null) return; if ("trustListOwner".equals(rawName)) { trustListOwnerTag = true; } else if (trustListOwnerTag && "nick".equals(rawName)) { nickTag = true; } else if (trustListOwnerTag && "publicKey".equals(rawName)) { publicKeyTag = true; } else super.startElement(nameSpaceURI, localName, rawName, attrs); } public void characters(char[] ch, int start, int end) throws SAXException { String txt = new String(ch, start, end); if (trustListOwnerTag && nickTag) nick = txt; else if (trustListOwnerTag && publicKeyTag) publicKey = txt; else super.characters(ch, start, end); } public void endElement(String nameSpaceURI, String localName, String rawName) throws SAXException { if (rawName == null) { rawName = localName; } if (rawName == null) return; if ("trustListOwner".equals(rawName)) { trustListOwnerTag = false; } else if (trustListOwnerTag && "nick".equals(rawName)) { nickTag = false; } else if (trustListOwnerTag && "publicKey".equals(rawName)) { publicKeyTag = false; } else super.endElement(nameSpaceURI, localName, rawName); } public void updateIdentity(Identity i) { /* TODO : Check the signature of the trust list */ } public boolean trustListIsValid() { boolean hasExpectedOwner = false; hasExpectedOwner = (getNick().equals(nick)) && (getPublicKey().equals(publicKey)); return hasExpectedOwner; } public void start() { } public void end() { } } public boolean doSecurityChecks(File trustList) { TrustListSecurityHandler handler = new TrustListSecurityHandler(); TrustListParser.importTrustList((TrustListParser.TrustListHandler)handler, trustList); return handler.trustListIsValid(); } public boolean loadTrustList(File trustList) { try { TrustListParser.importTrustList(this, trustList); } catch(Exception e) { Logger.error(this, "Exception while parsing the trust list of '"+toString()+"' : '"+e.toString()+"' => trust list ignored"); purgeTrustList(); return false; } return true; } private PreparedStatement insertTrustLinkSt = null; public void start() { try { insertTrustLinkSt = getDb().getConnection().prepareStatement("INSERT INTO wotTrustLists (source, destination, trustLevel) VALUES (?, ?, ?)"); } catch(SQLException e) { Logger.error(this, "Error while updating a trust list in the db (3) : "+e.toString()); return; } purgeTrustList(); } public void purgeTrustList() { try { synchronized(getDb().dbLock) { PreparedStatement st; st = getDb().getConnection().prepareStatement("DELETE FROM wotTrustLists WHERE source = ?"); st.setInt(1, getId()); st.execute(); st.close(); } } catch(SQLException e) { Logger.error(this, "Error while updating a trust list in the db (1) : "+e.toString()); e.printStackTrace(); } } public void end() { try { insertTrustLinkSt.close(); insertTrustLinkSt = null; } catch(SQLException e) { } } public void updateIdentity(Identity i) { if (i.getTrustLevel() == 0 || i.getTrustLevel() < Identity.trustLevelInt[Identity.trustLevelInt.length-1] || i.getTrustLevel() > Identity.trustLevelInt[1]) { Logger.error(this, "Invalid trust level in the trust list of '"+toString()+"' !"); throw new RuntimeException("Invalid trust level in the trust list of '"+toString()+"' !"); } Identity target = Identity.getIdentity(getDb(), i.getNick(), i.getPublicKey()); if (target == null) { Logger.notice(this, "Minor problem while parsing the trust list (1)"); return; } try { synchronized(getDb().dbLock) { insertTrustLinkSt.setInt(1, getId()); insertTrustLinkSt.setInt(2, target.getId()); insertTrustLinkSt.setInt(3, i.getTrustLevel()); insertTrustLinkSt.execute(); } } catch(SQLException e) { Logger.error(this, "Error while updating a trust list in the db (2) : "+e.toString()); e.printStackTrace(); } } public void updateInfos(String wotPublicKey, java.util.Date lastDownload) { try { synchronized(getDb().dbLock) { PreparedStatement st; st = getDb().getConnection().prepareStatement("UPDATE wotKeys SET publicKey = ?, keyDate = ?, lastDownload = ? WHERE sigId = ?"); st.setString(1, wotPublicKey); st.setTimestamp(2, new Timestamp(new java.util.Date().getTime())); st.setTimestamp(3, new Timestamp(lastDownload.getTime())); st.setInt(4, getId()); st.execute(); st.close(); } } catch(SQLException e) { Logger.error(this, "Error while updating infos in the wotKeys table : "+e.toString()); e.printStackTrace(); } } public String getWoTPublicKey() { try { synchronized(getDb().dbLock) { PreparedStatement st; st = getDb().getConnection().prepareStatement("SELECT publicKey FROM wotKeys WHERE sigId = ? LIMIT 1"); st.setInt(1, getId()); ResultSet set = st.executeQuery(); if (!set.next()) { st.close(); return null; } String r = set.getString("publicKey"); st.close(); return r; } } catch(SQLException e) { Logger.error(this, "Unable to check if an identity is in the WoT because : "+e.toString()); } return null; } /** * Just a container * @author jflesch */ public static class TrustLink { private WotIdentity src; private WotIdentity dst; private Identity destinationAsSeenByTheSource; public TrustLink(Hsqldb db, WotIdentity src, WotIdentity dst, int linkTrustLevel) { this.src = src; this.dst = dst; destinationAsSeenByTheSource = new Identity(db, dst.getId(), dst.getNick(), dst.getPublicKey(), dst.getPrivateKey(), dst.isDup(), linkTrustLevel); } public WotIdentity getSource() { return src; } public WotIdentity getDestination() { return dst; } public int getLinkTrustLevel() { return destinationAsSeenByTheSource.getTrustLevel(); } public Identity getDestinationAsSeenByTheSource() { return destinationAsSeenByTheSource; } } public Vector getTrustList() { return getTrustList(getDb(), this); } /** * @param db * @param idSrc * @return a vector of TrustLink */ public static Vector getTrustList(Hsqldb db, Identity idSrc) { Vector v = new Vector(); WotIdentity src = new WotIdentity(idSrc); if (idSrc.getPrivateKey() != null) { /* mode lazy bastard => on */ Vector oids = getOtherWotIdentities(db); for (Iterator it = oids.iterator(); it.hasNext() ; ) { WotIdentity id = (WotIdentity)it.next(); v.add(new TrustLink(db, src, id, id.getUserTrustLevel())); } return v; } try { synchronized(db.dbLock) { PreparedStatement st; st = db.getConnection().prepareStatement("SELECT signatures.id AS id, "+ " signatures.nickname AS nickname, "+ " signatures.publicKey AS publicKey, "+ " signatures.privateKey AS privateKey, "+ " signatures.isDup AS isDup, "+ " signatures.trustLevel AS yourTrustLevel, "+ " wotTrustLists.trustLevel AS linkTrustLevel "+ "FROM wotTrustLists INNER JOIN signatures ON wotTrustLists.destination = signatures.id "+ "WHERE wotTrustLists.source = ?"); st.setInt(1, idSrc.getId()); ResultSet set = st.executeQuery(); while(set.next()) { WotIdentity dst = new WotIdentity(new Identity(db, set.getInt("id"), set.getString("nickName"), set.getString("publicKey"), set.getString("privateKey"), set.getBoolean("isDup"), set.getInt("yourTrustLevel"))); int linkTrustLevel = set.getInt("linkTrustLevel"); TrustLink l = new TrustLink(db, src, dst, linkTrustLevel); v.add(l); } st.close(); } } catch(SQLException e) { Logger.error(new WotIdentity(), "Error while getting trust list : "+e.toString()); e.printStackTrace(); } return v; } /** * Returns only the identities with a trust > 0 */ public static Vector getOtherWotIdentities(Hsqldb db) { Vector v = new Vector(); try { synchronized(db.dbLock) { PreparedStatement st; st = db.getConnection().prepareStatement("SELECT signatures.id AS id, "+ " signatures.nickname AS nickname, "+ " signatures.publicKey AS publicKey, "+ " signatures.privateKey AS privateKey, "+ " signatures.isDup AS isDup, "+ " signatures.trustLevel AS trustLevel "+ "FROM wotKeys INNER JOIN signatures ON wotKeys.sigId = signatures.id "+ "WHERE signatures.privateKey IS NULL "+ "AND signatures.trustLevel >= 0"); ResultSet set = st.executeQuery(); /* TODO : Optimize if possible */ while(set.next()) { WotIdentity wi = new WotIdentity(new Identity(db, set.getInt("id"), set.getString("nickName"), set.getString("publicKey"), set.getString("privateKey"), set.getBoolean("isDup"), set.getInt("trustLevel"))); if (wi.getTrustLevel() > 0 && wi.getTrustLevel() != Identity.trustLevelInt[0]) v.add(wi); } st.close(); } } catch(SQLException e) { Logger.error(new WotIdentity(), "Error while gettings identities used in the WoT : "+e.toString()); e.printStackTrace(); } return v; } }