/* * Part of the CCNx Java Library. * * Copyright (C) 2010 Palo Alto Research Center, Inc. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 2.1 * as published by the Free Software Foundation. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. You should have received * a copy of the GNU Lesser General Public License along with this library; * if not, write to the Free Software Foundation, Inc., 51 Franklin Street, * Fifth Floor, Boston, MA 02110-1301 USA. */ package org.ccnx.ccn.impl.security.keys; import java.io.IOException; import java.security.PublicKey; import org.ccnx.ccn.CCNHandle; import org.ccnx.ccn.KeyManager; import org.ccnx.ccn.impl.CCNFlowServer; import org.ccnx.ccn.io.content.PublicKeyObject; import org.ccnx.ccn.protocol.ContentName; import org.ccnx.ccn.protocol.KeyLocator; import org.ccnx.ccn.protocol.PublisherPublicKeyDigest; /** * A small class to handle publishing keys to CCNx, without requiring a repository * to be present. This class publishes our keys, only if someone asks for them. It doesn't make its own * handle, unless really asked to. * TODO move to use the default handle, which requires making sure that the caller has the opportunity * to provide signing key information to us if they don't want to have it pulled from the default * handle. */ public class KeyServer { protected CCNHandle _handle = null; protected CCNFlowServer _keyServer = null; /** * Constructor; uses existing handle. * @param handle */ public KeyServer(CCNHandle handle) { _handle = handle; } public CCNHandle handle() { return _handle; } public synchronized void initialize() throws IOException { if (isInitialized()) { return; } // everyone can ask us for keys even if we have no repository // make a buffered server to return key data _keyServer = new CCNFlowServer(null, true, handle()); } public synchronized boolean isInitialized() { return (null != _keyServer); } /** * Start serving signed records for this key. * We used to check to see if this key was already on the network before publishing * it. That was silly -- the interest mechanism would do this for us. Much better way * to handle things is to just listen for interests for this key, and only publish it * if someone asks (we really want to be the server of last resort, so we should answer * late, but don't know how to do that). So we could make an interest handler and then * publish the key on first interest (and assume it's cached thereafter?). If the cost * of signing is negligible, we can be cheezier. Just publish to our key server, and * if someone comes looking, they'll get it. If not.... * * @param keyName the key's content name. Will add a version when saving if it doesn't * have one already. If it does have a version, will use that one (see below for effect * of version on the key locator). (Note that this is not * standard behavior for savable network content, which needs its version explicitly * set.) * @param keyToPublish the public key to publish * @param keyID the publisher id * @param signingKeyID the key id of the key pair to sign with * @param signingKeyLocator the key locator to use if we save this key (if it is not already published). * If not specified, we look for the default locator for the signing key. If there is none, * and we are signing with the same key we are publishing, we build a * self-referential key locator, using the name passed in (versioned or not). * @return the published information about this key * @throws IOException */ public PublicKeyObject serveKey(ContentName keyName, PublicKey keyToPublish, PublisherPublicKeyDigest signingKeyID, KeyLocator signingKeyLocator) throws IOException { // Set up key server if it hasn't been set up already initialize(); // Use the key publishing framework in KeyManager to format this key, but use our _keyServer // as the flow controller to serve it. _keyServer.addNameSpace(keyName); return KeyManager.publishKey(keyName, keyToPublish, signingKeyID, signingKeyLocator, _keyServer, null, null, _handle.keyManager()); } /** * Handle cases where people query us with short prefixes. The flow controller * will suppress duplicate or unnecessary registrations. * @param keyPrefix * @throws IOException */ public void respondToKeyRequests(ContentName keyPrefix) throws IOException { // Set up key server if it hasn't been set up already initialize(); _keyServer.addNameSpace(keyPrefix); } }