Package com.subgraph.orchid.circuits.hs

Source Code of com.subgraph.orchid.circuits.hs.HSDescriptorParser

package com.subgraph.orchid.circuits.hs;

import java.nio.ByteBuffer;
import java.util.logging.Logger;

import com.subgraph.orchid.TorParsingException;
import com.subgraph.orchid.crypto.TorSignature;
import com.subgraph.orchid.directory.DocumentFieldParserImpl;
import com.subgraph.orchid.directory.parsing.BasicDocumentParsingResult;
import com.subgraph.orchid.directory.parsing.DocumentFieldParser;
import com.subgraph.orchid.directory.parsing.DocumentObject;
import com.subgraph.orchid.directory.parsing.DocumentParser;
import com.subgraph.orchid.directory.parsing.DocumentParsingHandler;
import com.subgraph.orchid.directory.parsing.DocumentParsingResult;
import com.subgraph.orchid.directory.parsing.DocumentParsingResultHandler;
import com.subgraph.orchid.encoders.Base64;

public class HSDescriptorParser implements DocumentParser<HSDescriptor>{
  private static final Logger logger = Logger.getLogger(HSDescriptor.class.getName());
 
  private final DocumentFieldParser fieldParser;
  private final HSDescriptor descriptor;
  private final HSAuthentication authentication;
 
  private DocumentParsingResultHandler<HSDescriptor> resultHandler;
 
  public HSDescriptorParser(HiddenService hiddenService, DocumentFieldParser fieldParser) {
    this(hiddenService, fieldParser, null);
  }

  public HSDescriptorParser(HiddenService hiddenService, DocumentFieldParser fieldParser, HSDescriptorCookie cookie) {
    this.fieldParser = fieldParser;
    this.fieldParser.setHandler(createParsingHandler());
    this.descriptor = new HSDescriptor(hiddenService);
    this.authentication = new HSAuthentication(cookie);
  }
 
  private DocumentParsingHandler createParsingHandler() {
    return new DocumentParsingHandler() {
     
      public void parseKeywordLine() {
        processKeywordLine();
      }
     
      public void endOfDocument() {
      }
    };
  }

  public boolean parse(DocumentParsingResultHandler<HSDescriptor> resultHandler) {
    this.resultHandler = resultHandler;
    fieldParser.startSignedEntity();
    try {
      fieldParser.processDocument();
      return true;
    } catch(TorParsingException e) {
      resultHandler.parsingError(e.getMessage());
      return false;
    }
  }
 
 
  public DocumentParsingResult<HSDescriptor> parse() {
    final BasicDocumentParsingResult<HSDescriptor> result = new BasicDocumentParsingResult<HSDescriptor>();
    parse(result);
    return result;
  }

  private void processKeywordLine() {
    final HSDescriptorKeyword keyword = HSDescriptorKeyword.findKeyword(fieldParser.getCurrentKeyword());
    if(!keyword.equals(HSDescriptorKeyword.UNKNOWN_KEYWORD)) {
      processKeyword(keyword);
    }
  }
 
  private void processKeyword(HSDescriptorKeyword keyword) {
    switch(keyword) {
    case RENDEZVOUS_SERVICE_DESCRIPTOR:
      descriptor.setDescriptorId(fieldParser.parseBase32Digest());
      break;
    case VERSION:
      if(fieldParser.parseInteger() != 2) {
        throw new TorParsingException("Unexpected Descriptor version");
      }
      break;
     
    case PERMANENT_KEY:
      descriptor.setPermanentKey(fieldParser.parsePublicKey());
      break;
     
    case SECRET_ID_PART:
      descriptor.setSecretIdPart(fieldParser.parseBase32Digest());
      break;
     
    case PUBLICATION_TIME:
      descriptor.setPublicationTime(fieldParser.parseTimestamp());
      break;
     
    case PROTOCOL_VERSIONS:
      descriptor.setProtocolVersions(fieldParser.parseIntegerList());
      break;
     
    case INTRODUCTION_POINTS:
      processIntroductionPoints();
      break;
     
    case SIGNATURE:
      processSignature();
      break;
    case UNKNOWN_KEYWORD:
      break;
    }
  }
 
  private void processIntroductionPoints() {
    final DocumentObject ob = fieldParser.parseObject();
    final ByteBuffer buffer = createIntroductionPointBuffer(ob);
    final IntroductionPointParser parser = new IntroductionPointParser(new DocumentFieldParserImpl(buffer));
    parser.parse(new DocumentParsingResultHandler<IntroductionPoint>() {

      public void documentParsed(IntroductionPoint document) {
        logger.fine("adding intro point "+ document.getIdentity());
        descriptor.addIntroductionPoint(document);
      }

      public void documentInvalid(IntroductionPoint document, String message) {
        logger.info("Invalid introduction point received");
      }

      public void parsingError(String message) {
        logger.info("Error parsing introduction points: "+ message);
      }
    });
  }

  private ByteBuffer createIntroductionPointBuffer(DocumentObject ob) {
    final byte[] content = Base64.decode(ob.getContent(false));
    if(content[0] == 'i') {
      return ByteBuffer.wrap(content);
    } else {
      try {
        byte[] decrypted = authentication.decryptIntroductionPoints(content);
        return ByteBuffer.wrap(decrypted);
      } catch (HSAuthenticationException e) {
        throw new TorParsingException("Failed to decrypt introduction points: "+ e.getMessage());
      }
    }
  }

  private void processSignature() {
    fieldParser.endSignedEntity();
    final TorSignature signature = fieldParser.parseSignature();
    if(!fieldParser.verifySignedEntity(descriptor.getPermanentKey(), signature)) {
      resultHandler.documentInvalid(descriptor, "Signature verification failed");
      fieldParser.logWarn("Signature failed for descriptor: "+ descriptor.getDescriptorId().toBase32());
      return;
    }
    resultHandler.documentParsed(descriptor);
  }
}
TOP

Related Classes of com.subgraph.orchid.circuits.hs.HSDescriptorParser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.