001: /*
002: * Copyright 2001-2003 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.jndi.ldap.sasl;
027:
028: import javax.security.sasl.Sasl;
029: import javax.security.sasl.SaslClient;
030: import javax.security.sasl.SaslException;
031: import java.io.IOException;
032: import java.io.FilterOutputStream;
033: import java.io.OutputStream;
034:
035: class SaslOutputStream extends FilterOutputStream {
036: private static final boolean debug = false;
037:
038: private byte[] lenBuf = new byte[4]; // buffer for storing length
039: private int rawSendSize = 65536;
040: private SaslClient sc;
041:
042: SaslOutputStream(SaslClient sc, OutputStream out)
043: throws SaslException {
044: super (out);
045: this .sc = sc;
046:
047: if (debug) {
048: System.err.println("SaslOutputStream: " + out);
049: }
050:
051: String str = (String) sc
052: .getNegotiatedProperty(Sasl.RAW_SEND_SIZE);
053: if (str != null) {
054: try {
055: rawSendSize = Integer.parseInt(str);
056: } catch (NumberFormatException e) {
057: throw new SaslException(Sasl.RAW_SEND_SIZE
058: + " property must be numeric string: " + str);
059: }
060: }
061: }
062:
063: // Override this method to call write(byte[], int, int) counterpart
064: // super.write(int) simply calls out.write(int)
065:
066: public void write(int b) throws IOException {
067: byte[] buffer = new byte[1];
068: buffer[0] = (byte) b;
069: write(buffer, 0, 1);
070: }
071:
072: /**
073: * Override this method to "wrap" the outgoing buffer before
074: * writing it to the underlying output stream.
075: */
076: public void write(byte[] buffer, int offset, int total)
077: throws IOException {
078: int count;
079: byte[] wrappedToken, saslBuffer;
080:
081: // "Packetize" buffer to be within rawSendSize
082: if (debug) {
083: System.err.println("Total size: " + total);
084: }
085:
086: for (int i = 0; i < total; i += rawSendSize) {
087:
088: // Calculate length of current "packet"
089: count = (total - i) < rawSendSize ? (total - i)
090: : rawSendSize;
091:
092: // Generate wrapped token
093: wrappedToken = sc.wrap(buffer, offset + i, count);
094:
095: // Write out length
096: intToNetworkByteOrder(wrappedToken.length, lenBuf, 0, 4);
097:
098: if (debug) {
099: System.err.println("sending size: "
100: + wrappedToken.length);
101: }
102: out.write(lenBuf, 0, 4);
103:
104: // Write out wrapped token
105: out.write(wrappedToken, 0, wrappedToken.length);
106: }
107: }
108:
109: public void close() throws IOException {
110: SaslException save = null;
111: try {
112: sc.dispose(); // Dispose of SaslClient's state
113: } catch (SaslException e) {
114: // Save exception for throwing after closing 'in'
115: save = e;
116: }
117: super .close(); // Close underlying output stream
118:
119: if (save != null) {
120: throw save;
121: }
122: }
123:
124: // Copied from com.sun.security.sasl.util.SaslImpl
125: /**
126: * Encodes an integer into 4 bytes in network byte order in the buffer
127: * supplied.
128: */
129: private static void intToNetworkByteOrder(int num, byte[] buf,
130: int start, int count) {
131: if (count > 4) {
132: throw new IllegalArgumentException(
133: "Cannot handle more than 4 bytes");
134: }
135:
136: for (int i = count - 1; i >= 0; i--) {
137: buf[start + i] = (byte) (num & 0xff);
138: num >>>= 8;
139: }
140: }
141: }
|