From 9f5054d2a37060dd811f02c09090ca968e8d9c2e Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Mon, 12 Nov 2012 14:26:08 -0500 Subject: [PATCH] moving the shell functions into a jruby script --- README.md | 23 ++ src/main/java/com/hashbangbash/trie/App.java | 315 ------------------- tools/handy.rb | 82 ++++- 3 files changed, 100 insertions(+), 320 deletions(-) delete mode 100644 src/main/java/com/hashbangbash/trie/App.java diff --git a/README.md b/README.md index 1407e95..10b27b4 100644 --- a/README.md +++ b/README.md @@ -23,3 +23,26 @@ You can use either ant, or maven. I included the only two jar deps, for local tools and ant builds. But the unit tests are currently run with maven. + +Tools +===== + +The CLI class was done away with, so as not to ship in the jar, anything uneeded for +the library. It's been rewritten in jRuby (see http://jruby.org/ ). +The script ./tools/handy.rb, has plenty of functionality, and feel free to add more. + +** Usage + $> jruby tools/handy.rb --help + Usage: handy [options] + --dot output the dot digraph of content listing (defaults to ./src/test/resources/contents.list + --contents FILE use FILE instead of ./src/test/resources/contents.list + --cert FILE read contents from certificate FILE + --test PATH validate PATH, instead of [/content/beta/rhel/server/5/5server/x86_64/sap/os/repomd.xml] + --print print the tree of contents + + $> jruby ./tools/handy.rb --dot > contents.dot && dot -Tpng contents.dot -o contents.png && display contents.png + + $> jruby ./tools/handy.rb --cert ./src/test/resources/test-certv3.pem + [/content/beta/rhel/server/5/5server/x86_64/sap/os/repomd.xml] true + [/foo/path, /foo/path/always/$releasever, /foo/path/never] + diff --git a/src/main/java/com/hashbangbash/trie/App.java b/src/main/java/com/hashbangbash/trie/App.java deleted file mode 100644 index 74d681e..0000000 --- a/src/main/java/com/hashbangbash/trie/App.java +++ /dev/null @@ -1,315 +0,0 @@ -package com.hashbangbash.trie; - -import java.util.List; -import java.util.ArrayList; - -import java.io.InputStream; -import java.io.DataInputStream; -import java.io.FileInputStream; -import java.io.InputStreamReader; -import java.io.BufferedReader; -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileOutputStream; - -import java.io.FileNotFoundException; -import java.io.IOException; - -import com.redhat.trie.HuffNode; -import com.redhat.trie.NodePair; -import com.redhat.trie.PathNode; -import com.redhat.trie.PathTree; -import com.redhat.trie.PayloadException; - -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.security.cert.CertificateFactory; - -import org.bouncycastle.asn1.DEROctetString; -import org.bouncycastle.asn1.ASN1Encodable; -import org.bouncycastle.x509.extension.X509ExtensionUtil; - - -/* - * App - * - * This is just a simple class to handle command line interactions - * - */ -public class App { - - /* - * PrettyPrint a PathNode tree - */ - public static void printTree(PathNode pn, int tab) { - StringBuffer nodeRep = new StringBuffer(); - for (int i = 0; i <= tab; i++) { - nodeRep.append(" "); - } - nodeRep.append("Node ["); - nodeRep.append(pn.getId()); - nodeRep.append("]"); - - for (PathNode parent : pn.getParents()) { - nodeRep.append(" ^ ["); - nodeRep.append(parent.getId()); - nodeRep.append("]"); - } - for (NodePair cp : pn.getChildren()) { - nodeRep.append(" v ["); - nodeRep.append(cp.getName()); - nodeRep.append(" {"); - nodeRep.append(cp.getConnection().getId()); - nodeRep.append("} ]"); - } - System.out.println(nodeRep); - for (NodePair cp : pn.getChildren()) { - printTree(cp.getConnection(), tab + 1); - } - } - - /* - * PrettyPrint a HuffNode tree - */ - public static void printTrie(HuffNode hn, int tab) { - StringBuffer nodeRep = new StringBuffer(); - for (int i = 0; i <= tab; i++) { - nodeRep.append(" "); - } - nodeRep.append("Node ["); - nodeRep.append(hn.getId()); - nodeRep.append("]"); - - nodeRep.append(", Weight ["); - nodeRep.append(hn.getWeight()); - nodeRep.append("]"); - - nodeRep.append(", Value = ["); - nodeRep.append(hn.getValue()); - nodeRep.append("]"); - - System.out.println(nodeRep); - if (hn.getLeft() != null) { - printTrie(hn.getLeft(), tab + 1); - } - if (hn.getRight() != null) { - printTrie(hn.getRight(), tab + 1); - } - } - - /* - * From the deflated payload, produce the content set lists - * - * - * FIXME - break this apart, so that the hydrated payload - * can be structure to more quickly search, and use less memory - * - * Rename it for tracking, and to be clear about what is happening - */ - public static List hydrateContentPackage(byte[] compressedBlob) { - PathTree pt = new PathTree(compressedBlob); - return pt.toList(); - } - - - public static ASN1Encodable objectFromOid(X509Certificate cert, String oid) { - if (cert == null) { return null; } - - try { - for (String thisOid : cert.getNonCriticalExtensionOIDs()) { - if (thisOid.equals(oid)) { - return X509ExtensionUtil.fromExtensionValue(cert.getExtensionValue(oid)); - } - } - } catch (IOException ex) { } - return null; - } - - public static byte[] getBytesFromFile(File file) throws IOException { - InputStream is = new FileInputStream(file); - - // Get the size of the file - long length = file.length(); - - // You cannot create an array using a long type. - // It needs to be an int type. - // Before converting to an int type, check - // to ensure that file is not larger than Integer.MAX_VALUE. - if (length > Integer.MAX_VALUE) { - // File is too large - } - - // Create the byte array to hold the data - byte[] bytes = new byte[(int)length]; - - // Read in the bytes - int offset = 0; - int numRead = 0; - while (offset < bytes.length - && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) { - offset += numRead; - } - - // Ensure all the bytes have been read in - if (offset < bytes.length) { - throw new IOException("Could not completely read file "+file.getName()); - } - - // Close the input stream and return bytes - is.close(); - return bytes; - } - - - public static List hydrateFromBytes(byte[] compressedBlob) { - return hydrateContentPackage(compressedBlob); - } - - public static List hydrateFromFile(String filename) { - try { - return hydrateFromBytes(getBytesFromFile(new File(filename))); - } catch (IOException ex) { - System.out.println(ex); - } - return null; - } - - public static void byteArrayToFile(byte[] output, String filename) { - try { - FileOutputStream fos = new FileOutputStream(filename); - - /* - * To write byte array to a file, use - * void write(byte[] bArray) method of Java FileOutputStream class. - * - * This method writes given byte array to a file. - */ - fos.write(output); - - /* - * Close FileOutputStream using, - * void close() method of Java FileOutputStream class. - * - */ - fos.flush(); - fos.close(); - - } catch(FileNotFoundException ex) { - System.out.println("FileNotFoundException : " + ex); - } catch(IOException ioe) { - System.out.println("IOException : " + ioe); - } - } - - public static List listFromFile(String filename) throws IOException, FileNotFoundException { - FileInputStream fis; - DataInputStream in; - BufferedReader br; - - String content; - List contentList; - - try { - fis = new FileInputStream(filename); - } catch (FileNotFoundException ex) { - throw ex; - } catch (Throwable t) { - System.out.printf("ERROR: [%s] %s\n", filename, t); - return new ArrayList(); - } - - in = new DataInputStream(fis); - br = new BufferedReader(new InputStreamReader(in)); - contentList = new ArrayList(); - - try { - while ((content = br.readLine()) != null) { - contentList.add(content); - } - } catch (IOException ex) { - throw ex; - } - return contentList; - } - - public static void showTree(String filename) { - List contentList; - try { - contentList = listFromFile(filename); - } catch (IOException ex) { - System.out.printf("ERROR: [%s] - %s\n", filename, ex); - return; - } - showTree(contentList); - } - - public static void showTree(List contentList) { - PathTree pt; - try { - pt = new PathTree(contentList); - printTree(pt.getRootPathNode(), 0); - } catch (PayloadException ex) { - System.out.println(ex); - } - } - - public static ASN1Encodable objectFromCertOid(String certFilename, String oid) { - X509Certificate cert; - cert = certFromFile(certFilename); - return objectFromOid(cert,oid); - } - - public static X509Certificate certFromFile(String certFilename) { - FileInputStream fis; - BufferedInputStream bis; - CertificateFactory cf; - X509Certificate cert; - - try { - fis = new FileInputStream(certFilename); - } catch (FileNotFoundException ex) { - return null; - } - - bis = new BufferedInputStream(fis); - - - try { - cf = CertificateFactory.getInstance("X.509"); - } catch (CertificateException ex) { - return null; - } - - try { - while (bis.available() > 0) { - cert = (X509Certificate) cf.generateCertificate(bis); - return cert; - } - } catch (IOException ex) { - } catch (CertificateException cex) { - } - return null; - } - - public static void main(String[] args) { - for (String arg : args) { - //showTreeFromCSFIle(arg); - //showTreeFromCSFIle(arg); - - DEROctetString dos; - List contents; - - dos = (DEROctetString)objectFromCertOid(arg, "1.3.6.1.4.1.2312.9.7"); - //byteArrayToFile(dos.getOctets(), "herp.bin"); - if ((contents = hydrateFromBytes(dos.getOctets())) == null) { - System.out.println("FAIL"); - return; - } - - for (String content : contents) { - System.out.println(content); - } - } - } -} - diff --git a/tools/handy.rb b/tools/handy.rb index c302f80..a0c4a58 100755 --- a/tools/handy.rb +++ b/tools/handy.rb @@ -5,9 +5,19 @@ require 'java' Dir[File.join(BASE_DIR,'lib/*jar')].each {|j| require j } Dir[File.join(BASE_DIR,'target/*jar')].each {|j| require j } +require 'openssl' require 'stringio' require 'optparse' +import java.io.BufferedInputStream +import java.io.FileInputStream +import java.security.cert.X509Certificate +import java.security.cert.CertificateFactory + +import org.bouncycastle.asn1.DEROctetString +import org.bouncycastle.asn1.ASN1Encodable +import org.bouncycastle.x509.extension.X509ExtensionUtil + module Trie include_package 'com.redhat.trie' end @@ -44,12 +54,31 @@ def write_children(io, node) end end -def get_end(node) - return node if node.getChildren().length == 0 +# PrettyPrint a PathNode or HuffNode tree +def printTree(node, tab) + nodeRep = " " * tab + + nodeRep += "Node [#{node.getId}]" + nodeRep += ", Weight [#{node.getWeight}]" if node.respond_to? :getWeight + nodeRep += ", Value = [#{node.getValue}]" if node.respond_to? :getValue + node.getParents.each do |parent| + nodeRep += " ^ [#{parent.getId}]" + end if node.respond_to? :getParents node.getChildren.each do |child| - return get_end(child.getConnection()) + nodeRep += " v [#{child.getName} {#{child.getId}}]" + end if node.respond_to? :getChildren + + puts nodeRep + + node.getChildren.each do |child| + printTree(child.getConnection, tab+1) + end if node.respond_to? :getChildren + if node.respond_to?(:getLeft) and node.respond_to?(:getRight) + printTree(node.getLeft, tab+1) if node.getLeft != nil + printTree(node.getRight, tab+1) if node.getRight != nil end end + def parse_args(args) options = { :content_list => './src/test/resources/contents.list', @@ -63,9 +92,15 @@ def parse_args(args) opts.on('--contents FILE', "use FILE instead of #{options[:content_list]}") do |o| options[:content_list] = o end + opts.on('--cert FILE', "read contents from certificate FILE") do |o| + options[:certificate] = o + end opts.on('--test PATH', "validate PATH, instead of [#{options[:test_url]}]") do |o| options[:test_url] = o end + opts.on('--print', "print the tree of contents") do |o| + options[:printTree] = o + end end opts.parse!(args) @@ -73,6 +108,36 @@ def parse_args(args) return options end +# ick, using java to do SSL +def object_from_oid(cert, oid) + return unless cert + cert.getNonCriticalExtensionOIDs.each do |o| + if o == oid + return X509ExtensionUtil.fromExtensionValue(cert.getExtensionValue(o)) + end + end + return nil +end + +# ick, using java to do SSL +def value_from_oid(filename, oid) + bis = BufferedInputStream.new(FileInputStream.new(filename)) + cf = CertificateFactory.getInstance("X.509") + cert = cf.generateCertificate(bis) # this is an X509Certificate + + object_from_oid(cert, oid) +end + +# not working on jRuby. :-( +# https://github.com/jruby/jruby/issues/389 +def value_from_oid_bunk(filename, oid) + cert = OpenSSL::X509::Certificate.new(File.read(filename)) + ext = cert.extensions.detect {|ext| ext.oid == oid } + return if ext.nil? + + return OpenSSL::ASN1.decode(OpenSSL::ASN1.decode(ext.to_der).value[1].value).value +end + def main(args) options = parse_args(args) @@ -80,8 +145,15 @@ def main(args) puts print_dot(pt(options[:content_list]).getRootPathNode()).read() if options[:dot] - #pn = pt.getRootPathNode - #Trie::Util.printTree(pn, 0) + if options[:printTree] + pn = pt.getRootPathNode + printTree(pn, 0) + end + if options[:certificate] + data = value_from_oid(options[:certificate], '1.3.6.1.4.1.2312.9.7') + pt = Trie::PathTree.new(data.getOctets) + puts pt.toList() + end end main(ARGV) if $0 == __FILE__