/** * * Copyright 2004-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.geronimo.interop.rmi.iiop; import java.util.Random; import org.apache.geronimo.interop.util.BigEndian; import org.apache.geronimo.interop.util.UTF8; public class SecurityInfo { // public data public static final int TAG_USERNAME = BigEndian.getInt(new byte[] { (byte) 'U', (byte) 'S', (byte) 'E', (byte) 'R' }); public static final int TAG_PASSWORD = BigEndian.getInt(new byte[] { (byte) 'P', (byte) 'A', (byte) 'S', (byte) 'S' }); public static Random seedFactory = new Random(); public String username; public String password; private static ThreadLocal current = new ThreadLocal(); public static SecurityInfo getCurrent() { return (SecurityInfo) current.get(); } public static void setCurrent(SecurityInfo info) { current.set(info); } /** * * Encode a username or password to prevent accidental disclosure * * by packet sniffers etc. The intention is not to provide strong * * encryption, SSL should be used for that. * * * * Note: this algorithm is not to be changed, or it will cause * * version incompatibilites between client and server. See also * * similar requirements in Random.java. */ public static byte[] encode(String plainText) { int seed = seedFactory.nextInt(); // data race, but we don't care Random random = new Random(seed); byte[] utf8 = UTF8.fromString(plainText); int n = utf8.length; int pad = 0; // Try to mask password length by padding to 4 byte boundaries. while ((1 + n + pad) % 4 != 0) { pad++; } byte[] data = new byte[6 + n + pad]; data[0] = (byte) 'E'; // Can be overwritten by caller after return. BigEndian.setInt(data, 1, seed); data[5] = (byte) (pad + random.nextInt()); for (int i = 0; i < n + pad; i++) { if (i < n) { data[6 + i] = (byte) (utf8[i] + random.nextInt()); } else { data[6 + i] = (byte) random.nextInt(); // random padding. } } return data; } /** * * Inverse of encode. */ public static String decode(byte[] data) { int n = data.length - 6; if (n < 0) { throw new IllegalArgumentException("data.length = " + data.length); } int seed = BigEndian.getInt(data, 1); Random random = new Random(seed); int pad = ((data[5] - random.nextInt()) + 0x100) & 0xff; if (pad < 0 || pad > 3) { throw new IllegalArgumentException("pad = " + pad); } n -= pad; byte[] utf8 = new byte[n]; for (int i = 0; i < n; i++) { utf8[i] = (byte) (data[i + 6] - random.nextInt()); } String plainText = UTF8.toString(utf8); return plainText; } }