java/src/org/openantivirus/engine/credo CredoEntry.java,NONE,1.1 CredoEntryIterator.java,NONE,1.1 CredoException.java,NONE,1.1 CredoParser.java,NONE,1.1 CredoVerifier.java,NONE,1.1 CredoFile.java,NONE,1.1 StringsParser.java,NONE,1.1

[email protected]
Newsgroups gmane.comp.security.virus.openantivirus.cvs
Message-ID <[email protected]>
Update of /cvsroot/openantivirus/java/src/org/openantivirus/engine/credo
In directory sc8-pr-cvs1:/tmp/cvs-serv4777/java/src/org/openantivirus/engine/credo

Added Files:
	CredoEntry.java CredoEntryIterator.java CredoException.java 
	CredoParser.java CredoVerifier.java CredoFile.java 
	StringsParser.java 
Log Message:
Rewrite of the engine to use a virtual file system
Move to 'engine' subdirectory
Added bzip2 and tar decompressors
Switch from GPL to MPL

--- NEW FILE: CredoEntry.java ---
/*
 * $Id: CredoEntry.java,v 1.1 2003/12/14 11:08:26 kurti Exp $
 * 
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is OAV.
 *
 * The Initial Developer of the Original Code is Kurt Huwig <[email protected]>.
 * Portions created by the Initial Developer are Copyright (C) 2001-2003
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * ***** END LICENSE BLOCK ***** */

package org.openantivirus.engine.credo;

import java.util.jar.*;
import java.io.*;

/**
 * An entry in a Credo file; it is a simple wrapper for JarEntry
 *
 * Pattern-Roles:
 * @author  Kurt Huwig <[email protected]>
 * @version $Revision: 1.1 $
 */
public class CredoEntry {
    public static final String VERSION =
        "$Id: CredoEntry.java,v 1.1 2003/12/14 11:08:26 kurti Exp $";
    
    /**
     * Entry types
     */
    public static final int
        UNINITIALIZED = -1,
        UNKNOWN       = 0,
        STRINGS       = 1;
    
    /** containing file */
    private final JarInputStream jarInputStream;
    
    /** corresponding entry */
    private final JarEntry jarEntry;
    
    /** type of Entry; lazy initialization */
    private int type = UNINITIALIZED;
    
    public CredoEntry(JarInputStream jarInputStream, JarEntry jarEntry) {
        this.jarInputStream = jarInputStream;
        this.jarEntry       = jarEntry;
    }
    
    /**
     * @return InputStream of the entry's content
     */
    public InputStream getInputStream() throws IOException {
        return jarInputStream;
    }
    
    /**
     * @return type of entry
     */
    public int getType() {
        if (type == UNINITIALIZED) {
            final String name = jarEntry.getName();
            if (name.endsWith(".strings")) {
                type = STRINGS;
            } else {
                type = UNKNOWN;
            }
        }
        return type;
    }
    
    public JarEntry getJarEntry() {
        return jarEntry;
    }
}

--- NEW FILE: CredoEntryIterator.java ---
/*
 * $Id: CredoEntryIterator.java,v 1.1 2003/12/14 11:08:26 kurti Exp $
 * 
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is OAV.
 *
 * The Initial Developer of the Original Code is Kurt Huwig <[email protected]>.
 * Portions created by the Initial Developer are Copyright (C) 2001-2003
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * ***** END LICENSE BLOCK ***** */

package org.openantivirus.engine.credo;

import java.util.*;
import java.util.jar.*;
import java.io.*;

/**
 * CredoEntryIterator
 *
 * Pattern-Roles:
 * @author  Kurt Huwig <[email protected]>
 * @version $Revision: 1.1 $
 */
class CredoEntryIterator implements Iterator {
    public static final String VERSION =
        "$Id: CredoEntryIterator.java,v 1.1 2003/12/14 11:08:26 kurti Exp $";
    
    private final JarInputStream jarInputStream;
    
    /**
     * the next element to return or null if there is none
     */
    private Object nextElement = UNINITIALIZED;
    
    /** this value is set as 'nextElement' if 'hasNext' has not been called */
    private static final Object UNINITIALIZED = new Object();
    
    public CredoEntryIterator(JarInputStream jarInputStream) {
        this.jarInputStream = jarInputStream;
    }
    
    /**
     * Returns <tt>true</tt> if the iteration has more elements. (In other
     * words, returns <tt>true</tt> if <tt>next</tt> would return an element
     * rather than throwing an exception.)
     *
     * @return <tt>true</tt> if the iterator has more elements.
     */
    public boolean hasNext() {
        if (nextElement == UNINITIALIZED) {
            setNext();
        }
        return nextElement != null;
    }    
    
    /**
     * Returns the next element in the interation.
     *
     * @return the next element in the iteration.
     * @exception NoSuchElementException iteration has no more elements.
     */
    public Object next() {
        if (nextElement == UNINITIALIZED) {
            setNext();
        }
        if (nextElement == null) {
            throw new NoSuchElementException();
        }
        
        final Object result = nextElement;
        nextElement = UNINITIALIZED;
        return result;
    }
    
    /**
     *
     * Removes from the underlying collection the last element returned by the
     * iterator (optional operation).  This method can be called only once per
     * call to <tt>next</tt>.  The behavior of an iterator is unspecified if
     * the underlying collection is modified while the iteration is in
     * progress in any way other than by calling this method.
     *
     * @exception UnsupportedOperationException if the <tt>remove</tt>
     * 		  operation is not supported by this Iterator.
     *
     * @exception IllegalStateException if the <tt>next</tt> method has not
     * 		  yet been called, or the <tt>remove</tt> method has already
     * 		  been called after the last call to the <tt>next</tt>
     * 		  method.
     */
    public void remove() {
        throw new UnsupportedOperationException();
    }
    
    /**
     * sets the next element to the next element of the Enumeration or null,
     * if there is none
     */
    private void setNext() {
        JarEntry jarEntry;
        do {
            try {
                jarEntry = jarInputStream.getNextJarEntry();
            } catch (IOException ioe) {
                // happens at EOF
                jarEntry = null;
            }
        } while (jarEntry != null
                 && (jarEntry.isDirectory()
                     || jarEntry.getName().startsWith("META-INF/")));
        nextElement = (jarEntry != null
                       ? new CredoEntry(jarInputStream, jarEntry) : null);
    }
}

--- NEW FILE: CredoException.java ---
/*
 * $Id: CredoException.java,v 1.1 2003/12/14 11:08:26 kurti Exp $
 * 
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is OAV.
 *
 * The Initial Developer of the Original Code is Kurt Huwig <[email protected]>.
 * Portions created by the Initial Developer are Copyright (C) 2001-2003
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * ***** END LICENSE BLOCK ***** */

package org.openantivirus.engine.credo;

/**
 * Exception regarding Credo files
 *
 * Pattern-Roles:
 * @author  Kurt Huwig <[email protected]>
 * @version $Revision: 1.1 $
 */
public class CredoException extends Exception {
    public static final String VERSION =
        "$Id: CredoException.java,v 1.1 2003/12/14 11:08:26 kurti Exp $";
    
    public CredoException(String message) {
        super(message);
    }
}

--- NEW FILE: CredoParser.java ---
/*
 * $Id: CredoParser.java,v 1.1 2003/12/14 11:08:26 kurti Exp $
 * 
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is OAV.
 *
 * The Initial Developer of the Original Code is Kurt Huwig <[email protected]>.
 * Portions created by the Initial Developer are Copyright (C) 2001-2003
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * ***** END LICENSE BLOCK ***** */

package org.openantivirus.engine.credo;

import java.io.*;
import java.util.*;

import org.openantivirus.engine.*;
import org.openantivirus.engine.censor.trie.*;

/**
 * Reads in Credo-files and initializes the corresponding Finders
 *
 * Pattern-Roles:
 * @author  Kurt Huwig <[email protected]>
 * @version $Revision: 1.1 $
 */
public class CredoParser {
    public static final String VERSION =
        "$Id: CredoParser.java,v 1.1 2003/12/14 11:08:26 kurti Exp $";
    
    public static final int NO_VERIFY     = -1;
    public static final int DEFAULT_LEVEL =  3;
    
    private final ScanConfiguration scanConfiguration;
    private final StringsParser stringsParser;
    
    /**
     * @param verify if the digital signature of the Credo-files should be
     *               verified
     */
    public CredoParser(ScanConfiguration scannerConfiguration, Trie trie) {
        this.scanConfiguration = scannerConfiguration;
        
        stringsParser = new StringsParser(new StringFinder(trie));
    }
    
    /**
     * Recursively parses all credo files in this directory and subdirectories
     * if this is a directory; otherwise the file itself
     */
    public void parse(File file) throws CredoException, IOException {
        if (file.isDirectory()) {
            final File[] afFiles = file.listFiles(new FilenameFilter() {
                public boolean accept(File directory, String name) {
                    return name.endsWith(CredoFile.EXTENSION);
                }
            });
            for (int i = 0; i < afFiles.length; i++) {
                parse(afFiles[i]);
            }
        } else {
            doParse(new CredoFile(file));
        }
    }
    
    public void parse(InputStream is) throws CredoException, IOException {
        doParse(new CredoFile(is));
    }
    
    protected void doParse(CredoFile credoFile) throws CredoException,
                                                       IOException {
        for (Iterator it = credoFile.entries(); it.hasNext(); ) {
            final CredoEntry credoEntry = (CredoEntry) it.next();
            System.out.println("Reading '" + credoEntry.getJarEntry().getName()
                               + "'...");
            switch (credoEntry.getType()) {
                case CredoEntry.STRINGS:
                    stringsParser.parse(new InputStreamReader(
                            credoEntry.getInputStream()));
                    break;
                default:
                    throw new CredoException("Unknown CredoEntry-type: "
                                             + credoEntry.getType());
            }
            int verifyLevel = scanConfiguration.getInt("credo.level");
            if (verifyLevel != NO_VERIFY) {
                int credoLevel = CredoVerifier.verify(credoEntry);
                if (credoLevel < verifyLevel) {
                    throw new CredoException("Minimum Credo-level "
                            + verifyLevel + " > actual Credo-level "
                            + credoLevel);
                } else {
                    System.out.println("  verified Credo-level " + credoLevel);
                }
            }
        }
    }
}

--- NEW FILE: CredoVerifier.java ---
/*
 * $Id: CredoVerifier.java,v 1.1 2003/12/14 11:08:26 kurti Exp $
 * 
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is OAV.
 *
 * The Initial Developer of the Original Code is Kurt Huwig <[email protected]>.
 * Portions created by the Initial Developer are Copyright (C) 2001-2003
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * ***** END LICENSE BLOCK ***** */

package org.openantivirus.engine.credo;

import java.io.*;
import java.security.*;
import java.security.cert.*;
import java.security.cert.Certificate;

/**
 * Verifies digital signatures of Credo files
 *
 * Pattern-Roles:
 * @author  Kurt Huwig <[email protected]>
 * @version $Revision: 1.1 $
 */
public class CredoVerifier {
    public static final String VERSION =
        "$Id: CredoVerifier.java,v 1.1 2003/12/14 11:08:26 kurti Exp $";
    
    /** Number of signature levels */
    public static final int SIGNATURE_LEVELS = 4;
    
    /** Path to the signing certificate */
    private static final String CERTIFICATE_PATH = "/oav.cer";
    
    /** Type of the certificate */
    private static final String CERTIFICATE_TYPE = "X.509";
    
    /**
     * There can be only one! We trust noone besides ourselves :-)
     */
    private static final Certificate[] oavCertificate =
            new Certificate[SIGNATURE_LEVELS];
    
    private static final PublicKey[] oavPublicKey =
            new PublicKey[SIGNATURE_LEVELS];
    
    static {
        for (int level = 0; level < SIGNATURE_LEVELS; level++) {
            try {
                final InputStream is = CredoEntry.class.getResourceAsStream(
                        CERTIFICATE_PATH + ".level" + (level + 1));
                final CertificateFactory cf = CertificateFactory.getInstance(
                        CERTIFICATE_TYPE);
                oavCertificate[level] = cf.generateCertificate(is);
                try {
                    is.close();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
                oavPublicKey[level] = oavCertificate[level].getPublicKey();
            } catch (CertificateException ce) {
                ce.printStackTrace();
            }
        }
    }
    
    /**
     * Verifies the digital signature of this entry; the data of the entry
     * has to be read completely before calling this method.
     *
     * @throws CredoException If the digital signature is invalid
     * @return signature level
     */
    public static int verify(CredoEntry credoEntry) throws CredoException {
        final Certificate[] certificates =
                credoEntry.getJarEntry().getCertificates();
        if (certificates == null) {
            throw new CredoException(
                    "No signature found or entry not fully read");
        }
        int verifiedLevel = -1;
cert:   for (int i = 0; i < certificates.length; i++) {
            for (int level = 0; level < SIGNATURE_LEVELS; level++) {
                if (certificates[i].equals(oavCertificate[level])) {
                    continue cert;
                }
            }
            for (int level = 0; level < SIGNATURE_LEVELS; level++) {
                try {
                    certificates[i].verify(oavPublicKey[level]);
                    System.out.println("  signed by '"
                            + ((X509Certificate)certificates[i])
                              .getSubjectDN() + "'");
                    verifiedLevel = level;
                    //break cert;
                } catch (Exception e) {
                    // we have several certificates; all but one will fail
                }
            }
        }
        if (verifiedLevel == -1) {
            throw new CredoException("No valid signing certificate found");
        }
        return (verifiedLevel + 1);
    }    
}

--- NEW FILE: CredoFile.java ---
/*
 * $Id: CredoFile.java,v 1.1 2003/12/14 11:08:26 kurti Exp $
 * 
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is OAV.
 *
 * The Initial Developer of the Original Code is Kurt Huwig <[email protected]>.
 * Portions created by the Initial Developer are Copyright (C) 2001-2003
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * ***** END LICENSE BLOCK ***** */

package org.openantivirus.engine.credo;

import java.util.*;
import java.util.jar.*;
import java.io.*;

/**
 * A file containing scanning information
 *
 * Pattern-Roles:
 * @author  Kurt Huwig <[email protected]>
 * @version $Revision: 1.1 $
 */
public class CredoFile {
    public static final String VERSION =
        "$Id: CredoFile.java,v 1.1 2003/12/14 11:08:26 kurti Exp $";
    
    /** Filename extension of Credo-files */
    public static final String EXTENSION = ".credo";
    
    private final JarInputStream jarInputStream;
    
    public CredoFile(File file) throws CredoException {
        if (!file.exists()) {
            jarInputStream = null;
            throw new CredoException("Credo-File does not exist");
        }
        if (!file.isFile()) {
            jarInputStream = null;
            throw new CredoException("Credo-File is not a file");
        }
        
        try {
            jarInputStream = new JarInputStream(new FileInputStream(file));
        } catch( IOException ioe) {
            throw new CredoException(ioe.getMessage());
        }
    }
    
    public CredoFile(InputStream is) throws CredoException {
        if (is == null) {
            throw new CredoException("Credo-File not found");
        }
        try {
            jarInputStream = new JarInputStream(is);
        } catch (IOException ioe) {
            throw new CredoException(ioe.getMessage());
        }
    }
    
    /**
     * Returns all entries contained in the credo file
     *
     * @return Iterator of CredoEntry
     */
    public Iterator entries() {
        return new CredoEntryIterator(jarInputStream);
    }
}

--- NEW FILE: StringsParser.java ---
/*
 * $Id: StringsParser.java,v 1.1 2003/12/14 11:08:26 kurti Exp $
 * 
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is OAV.
 *
 * The Initial Developer of the Original Code is Kurt Huwig <[email protected]>.
 * Portions created by the Initial Developer are Copyright (C) 2001-2003
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * ***** END LICENSE BLOCK ***** */

package org.openantivirus.engine.credo;

import java.io.*;

import org.openantivirus.engine.censor.*;
import org.openantivirus.engine.censor.trie.*;

/**
 * Parses '.strings' credo files
 * 
 * Pattern-Roles:
 * @author  Kurt Huwig <[email protected]>
 * @version $Revision: 1.1 $
 */
public class StringsParser {
    private final StringFinder stringFinder;
    
    public StringsParser(StringFinder stringFinder) {
        this.stringFinder = stringFinder;
    }
    
    public void parse(Reader patternReader)
    throws IOException {

        final BufferedReader br = new BufferedReader(patternReader);
        
        String sLine;
        while ((sLine = br.readLine()) != null) {
            int iPos = sLine.indexOf('=');
            if (iPos == -1) {
                System.err.println("Malformed pattern line: " + sLine);
                continue;
            }
            
            String sVirusName = sLine.substring(0, iPos);
            String sPattern   = sLine.substring(iPos + 1);
            
            try {
                stringFinder.addString(hexToString(sPattern),
                        new StringVirusFoundListener(sVirusName));
            } catch (Exception e) {
                System.err.println(sLine);
                e.printStackTrace();
            }
        }
    }
    
    protected byte[] hexToString(String hex) {
        if (hex.length() % 2 != 0) {
            System.err.println("Malformed hexstring: " + hex);
            return null;
        }
        
        final byte[] result = new byte[hex.length() / 2];
        for (int i = 0; i < hex.length(); i += 2) {
            result[i / 2] = (byte) Integer.parseInt(hex.substring(i, i + 2),
                    16);
        }
        
        return result;
    }
    

    
    private class StringVirusFoundListener implements PositionFoundListener {
        private String virusName, pattern;
        
        public StringVirusFoundListener(String virusName) {
            this.virusName = virusName;
        }
        
        public void positionFound(PositionFoundEvent pfe)
        throws MalwareFoundException {
            throw new MalwareFoundException(virusName, pfe.entry);
        }
    }
    
}




-------------------------------------------------------
This SF.net email is sponsored by: SF.net Giveback Program.
Does SourceForge.net help you be more productive?  Does it
help you create better code?  SHARE THE LOVE, and help us help
YOU!  Click Here: http://sourceforge.net/donate/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.