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