001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    package org.apache.geronimo.converter.bea;
018    
019    import java.util.regex.Pattern;
020    import java.util.regex.Matcher;
021    import java.util.Properties;
022    import java.util.Iterator;
023    import java.lang.reflect.Method;
024    import java.lang.reflect.InvocationTargetException;
025    import java.io.File;
026    import java.io.FileInputStream;
027    import java.io.FileNotFoundException;
028    import java.io.BufferedReader;
029    import java.io.FileReader;
030    import java.io.StringWriter;
031    import java.io.PrintWriter;
032    import java.io.IOException;
033    import java.io.InputStream;
034    import java.net.URLClassLoader;
035    import java.net.URL;
036    
037    /**
038     * Reads information out of the WebLogic domain directory.
039     * Needs access to the WebLogic JARs in the weblogic81/server/lib directory.
040     *
041     * @version $Rev: 476049 $ $Date: 2006-11-16 23:35:17 -0500 (Thu, 16 Nov 2006) $
042     */
043    public class Weblogic81Utils {
044        private final static Pattern ENCRYPTED_STRING = Pattern.compile("\\\"\\{\\S+\\}\\S+?\\\"");
045        private Object decoder;
046        private Method decode;
047        private Object decrypter;
048        private Method decrypt;
049        private File domainDir;
050    
051        public Weblogic81Utils(String libDirPath, String domainDirPath) {
052            File libDir = new File(libDirPath);
053            if(!libDir.exists() || !libDir.canRead() || !libDir.isDirectory()) throw new IllegalArgumentException("Bad weblogic lib dir");
054            File weblogicJar = new File(libDir, "weblogic.jar");
055            File securityJar = new File(libDir, "jsafeFIPS.jar");
056            if(!weblogicJar.canRead()) throw new IllegalArgumentException("Cannot find JARs in provided lib dir");
057            domainDir = new File(domainDirPath);
058            if(!domainDir.exists() || !domainDir.canRead() || !domainDir.isDirectory()) throw new IllegalArgumentException("Bad domain directory");
059            File state = new File(domainDir, "SerializedSystemIni.dat");
060            if(!state.canRead()) throw new IllegalArgumentException("Cannot find serialized state in domain directory");
061            try {
062                ClassLoader loader = new URLClassLoader(securityJar.exists() ? new URL[]{weblogicJar.toURL(), securityJar.toURL()} : new URL[]{weblogicJar.toURL()}, Weblogic81Utils.class.getClassLoader());
063                initialize(loader, state);
064            } catch (Exception e) {
065                throw (RuntimeException)new IllegalArgumentException("Unable to initialize encryption routines from provided arguments").initCause(e);
066            }
067        }
068    
069        public Properties getBootProperties() {
070            File boot = new File(domainDir, "boot.properties");
071            FileInputStream bootIn = null;
072            try {
073                bootIn = new FileInputStream(boot);
074            } catch (FileNotFoundException e) {
075                return null;
076            }
077            try {
078                Properties props = new Properties();
079                props.load(bootIn);
080                bootIn.close();
081                for (Iterator it = props.keySet().iterator(); it.hasNext();) {
082                    String key = (String) it.next();
083                    String value = props.getProperty(key);
084                    if(value != null && value.startsWith("{")) props.setProperty(key, decryptString(value));
085                }
086                return props;
087            } catch (Exception e) {
088                return null;
089            }
090        }
091    
092        public String getConfigXML() throws FileNotFoundException {
093            File config = new File(domainDir, "config.xml");
094            BufferedReader in = new BufferedReader(new FileReader(config));
095            StringWriter string = new StringWriter();
096            PrintWriter out = new PrintWriter(string);
097            String line;
098            Matcher m = ENCRYPTED_STRING.matcher("");
099            try {
100                while((line = in.readLine()) != null) {
101                    m.reset(line);
102                    int last = -1;
103                    while(m.find()) {
104                        out.print(line.substring(last+1, m.start()));
105                        String s = line.substring(m.start(), m.end());
106                        out.print("\"");
107                        out.print(decryptString(s.substring(1, s.length()-1)));
108                        out.print("\"");
109                        last = m.end()-1;
110                    }
111                    if(last == -1) {
112                        out.println(line);
113                    } else {
114                        if(line.length() > last+1) {
115                            out.print(line.substring(last+1));
116                        }
117                        out.println();
118                    }
119                    out.flush();
120                }
121                in.close();
122                out.close();
123            } catch (Exception e) {
124                return null;
125            }
126            return string.getBuffer().toString();
127        }
128    
129        private void initialize(ClassLoader loader, File state) throws IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, ClassNotFoundException, InstantiationException {
130            byte[] salt = null, key = null;
131            FileInputStream in = new FileInputStream(state);
132            salt = readBytes(in);
133            int i = in.read();
134            if(i != -1) {
135                if(i != 1) throw new IllegalStateException();
136                key = readBytes(in);
137            }
138            in.close();
139            decrypter = getEncryptionService(loader, salt, key);
140            decoder = loader.loadClass("weblogic.utils.encoders.BASE64Decoder").newInstance();
141            decode = decoder.getClass().getMethod("decodeBuffer", new Class[]{String.class});
142            decrypt = decrypter.getClass().getMethod("decryptString", new Class[]{byte[].class});
143        }
144    
145        private static byte[] readBytes(InputStream in) throws IOException {
146            int len = in.read();
147            if(len < 0)
148                throw new IOException("stream is empty");
149            byte result[] = new byte[len];
150            int index = 0;
151            while(true) {
152                if(index >= len) {
153                    break;
154                }
155                int count = in.read(result, index, len - index);
156                if(count == -1)
157                    break;
158                index += count;
159            }
160            return result;
161        }
162    
163        private String decryptString(String string) throws IllegalAccessException, InvocationTargetException {
164            if(string.indexOf('}') > -1) {
165                string = string.substring(string.indexOf("}")+1);
166            }
167            return (String) decrypt.invoke(decrypter, new Object[]{decode.invoke(decoder, new Object[]{string})});
168        }
169    
170        static Object getEncryptionService(ClassLoader loader, byte salt[], byte key[]) throws NoSuchMethodException, ClassNotFoundException, IllegalAccessException, InvocationTargetException {
171            String magic = "0xccb97558940b82637c8bec3c770f86fa3a391a56";
172            Object factory = loader.loadClass("weblogic.security.internal.encryption.JSafeEncryptionServiceImpl").getMethod("getFactory", new Class[0]).invoke(null, null);
173            Method getter = factory.getClass().getMethod("getEncryptionService", new Class[]{byte[].class, String.class, byte[].class});
174            return getter.invoke(factory, new Object[]{salt, magic, key});
175        }
176    }