1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.server.ldap.handlers.bind;
21
22
23 import javax.security.sasl.Sasl;
24 import javax.security.sasl.SaslException;
25 import javax.security.sasl.SaslServer;
26
27 import org.apache.directory.shared.ldap.constants.SaslQoP;
28 import org.apache.mina.common.ByteBuffer;
29 import org.apache.mina.common.IoFilterAdapter;
30 import org.apache.mina.common.IoSession;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34
35
36
37
38
39
40
41
42
43
44
45
46 public class SaslFilter extends IoFilterAdapter
47 {
48 private static final Logger log = LoggerFactory.getLogger( SaslFilter.class );
49
50
51
52
53
54
55
56
57
58
59 public static final String DISABLE_SECURITY_LAYER_ONCE = SaslFilter.class.getName() + ".DisableSecurityLayerOnce";
60
61 private SaslServer saslServer;
62
63
64
65
66
67
68
69
70
71
72 public SaslFilter( SaslServer saslServer )
73 {
74 if ( saslServer == null )
75 {
76 throw new IllegalStateException();
77 }
78
79 this.saslServer = saslServer;
80 }
81
82
83 public void messageReceived( NextFilter nextFilter, IoSession session, Object message ) throws SaslException
84 {
85 log.debug( "Message received: {}", message );
86
87
88
89
90 String qop = ( String ) saslServer.getNegotiatedProperty( Sasl.QOP );
91 boolean hasSecurityLayer = ( qop != null && ( qop.equals( SaslQoP.QOP_AUTH_INT ) || qop.equals( SaslQoP.QOP_AUTH_CONF ) ) );
92
93 if ( hasSecurityLayer )
94 {
95
96
97
98 ByteBuffer buf = ( ByteBuffer ) message;
99 int bufferLength = buf.getInt();
100 byte[] bufferBytes = new byte[bufferLength];
101 buf.get( bufferBytes );
102
103 log.debug( "Will use SASL to unwrap received message of length: {}", bufferLength );
104 byte[] token = saslServer.unwrap( bufferBytes, 0, bufferBytes.length );
105 nextFilter.messageReceived( session, ByteBuffer.wrap( token ) );
106 }
107 else
108 {
109 log.debug( "Will not use SASL on received message." );
110 nextFilter.messageReceived( session, message );
111 }
112 }
113
114
115 public void filterWrite( NextFilter nextFilter, IoSession session, WriteRequest writeRequest ) throws SaslException
116 {
117 log.debug( "Filtering write request: {}", writeRequest );
118
119
120
121
122 if ( session.containsAttribute( DISABLE_SECURITY_LAYER_ONCE ) )
123 {
124
125 log.debug( "Disabling SaslFilter once; will not use SASL on write request." );
126 session.removeAttribute( DISABLE_SECURITY_LAYER_ONCE );
127 nextFilter.filterWrite( session, writeRequest );
128 return;
129 }
130
131
132
133
134 String qop = ( String ) saslServer.getNegotiatedProperty( Sasl.QOP );
135 boolean hasSecurityLayer = ( qop != null && ( qop.equals( SaslQoP.QOP_AUTH_INT ) || qop.equals( SaslQoP.QOP_AUTH_CONF ) ) );
136
137 ByteBuffer saslLayerBuffer = null;
138
139 if ( hasSecurityLayer )
140 {
141
142
143
144 ByteBuffer buf = ( ByteBuffer ) writeRequest.getMessage();
145 int bufferLength = buf.remaining();
146 byte[] bufferBytes = new byte[bufferLength];
147 buf.get( bufferBytes );
148
149 log.debug( "Will use SASL to wrap message of length: {}", bufferLength );
150
151 byte[] saslLayer = saslServer.wrap( bufferBytes, 0, bufferBytes.length );
152
153
154
155
156 saslLayerBuffer = ByteBuffer.allocate( 4 + saslLayer.length );
157 saslLayerBuffer.putInt( saslLayer.length );
158 saslLayerBuffer.put( saslLayer );
159 saslLayerBuffer.position( 0 );
160 saslLayerBuffer.limit( 4 + saslLayer.length );
161
162 log.debug( "Sending encrypted token of length {}.", saslLayerBuffer.limit() );
163 nextFilter.filterWrite( session, new WriteRequest( saslLayerBuffer, writeRequest.getFuture() ) );
164 }
165 else
166 {
167 log.debug( "Will not use SASL on write request." );
168 nextFilter.filterWrite( session, writeRequest );
169 }
170 }
171 }