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.ntlm;
21
22
23 import javax.naming.Context;
24 import javax.security.sasl.SaslException;
25
26 import org.apache.directory.api.ldap.model.constants.AuthenticationLevel;
27 import org.apache.directory.api.ldap.model.constants.SupportedSaslMechanisms;
28 import org.apache.directory.api.ldap.model.message.BindRequest;
29 import org.apache.directory.api.ldap.model.name.Dn;
30 import org.apache.directory.api.util.Strings;
31 import org.apache.directory.server.core.api.CoreSession;
32 import org.apache.directory.server.core.api.LdapPrincipal;
33 import org.apache.directory.server.core.api.interceptor.context.BindOperationContext;
34 import org.apache.directory.server.i18n.I18n;
35 import org.apache.directory.server.ldap.LdapSession;
36 import org.apache.directory.server.ldap.handlers.sasl.AbstractSaslServer;
37 import org.apache.directory.server.ldap.handlers.sasl.SaslConstants;
38
39
40
41
42
43
44
45
46
47 public class NtlmSaslServer extends AbstractSaslServer
48 {
49
50 enum NegotiationState
51 {
52 INITIALIZED, TYPE_1_RECEIVED, TYPE_2_SENT, TYPE_3_RECEIVED, COMPLETED
53 }
54
55
56 private NegotiationState state = NegotiationState.INITIALIZED;
57 private final NtlmProvider provider;
58
59
60 public NtlmSaslServer( NtlmProvider provider, BindRequest bindRequest, LdapSession ldapSession,
61 CoreSession adminSession )
62 {
63 super( ldapSession, adminSession, bindRequest );
64 this.provider = provider;
65 }
66
67
68
69
70
71 public String getMechanismName()
72 {
73 return SupportedSaslMechanisms.NTLM;
74 }
75
76
77 protected void responseRecieved()
78 {
79 switch ( state )
80 {
81 case INITIALIZED:
82 state = NegotiationState.TYPE_1_RECEIVED;
83 break;
84
85 case TYPE_1_RECEIVED:
86 throw new IllegalStateException( I18n.err( I18n.ERR_660 ) );
87
88 case TYPE_2_SENT:
89 state = NegotiationState.TYPE_3_RECEIVED;
90 break;
91
92 case TYPE_3_RECEIVED:
93 throw new IllegalStateException( I18n.err( I18n.ERR_661 ) );
94
95 case COMPLETED:
96 throw new IllegalStateException( I18n.err( I18n.ERR_662 ) );
97
98 default:
99 throw new IllegalStateException( "Unexpected negotiation state " + state );
100 }
101 }
102
103
104 protected void responseSent()
105 {
106 switch ( state )
107 {
108 case INITIALIZED:
109 throw new IllegalStateException( I18n.err( I18n.ERR_663 ) );
110
111 case TYPE_1_RECEIVED:
112 state = NegotiationState.TYPE_2_SENT;
113 break;
114
115 case TYPE_2_SENT:
116 throw new IllegalStateException( I18n.err( I18n.ERR_664 ) );
117
118 case TYPE_3_RECEIVED:
119 state = NegotiationState.COMPLETED;
120 break;
121
122 case COMPLETED:
123 throw new IllegalStateException( I18n.err( I18n.ERR_662 ) );
124
125 default:
126 throw new IllegalStateException( "Unexpected negotiation state " + state );
127 }
128 }
129
130
131
132
133
134 public byte[] evaluateResponse( byte[] response ) throws SaslException
135 {
136 if ( response == null )
137 {
138 throw new IllegalArgumentException( I18n.err( I18n.ERR_666 ) );
139 }
140
141 if ( response.length == 0 )
142 {
143 throw new IllegalArgumentException( I18n.err( I18n.ERR_667 ) );
144 }
145
146 responseRecieved();
147 byte[] retval = null;
148
149 switch ( state )
150 {
151 case TYPE_1_RECEIVED:
152 try
153 {
154 retval = provider.generateChallenge( getLdapSession().getIoSession(), response );
155 }
156 catch ( Exception e )
157 {
158 throw new SaslException( I18n.err( I18n.ERR_668 ), e );
159 }
160
161 break;
162
163 case TYPE_3_RECEIVED:
164 boolean result;
165 try
166 {
167 result = provider.authenticate( getLdapSession().getIoSession(), response );
168 Dn dn = getBindRequest().getDn();
169
170 if ( dn == null )
171 {
172 dn = new Dn( getLdapSession().getLdapServer().getDirectoryService().getSchemaManager() );
173 }
174 else if ( !dn.isSchemaAware() )
175 {
176 dn = new Dn( getLdapSession().getLdapServer().getDirectoryService().getSchemaManager(), dn );
177 }
178
179 LdapPrincipalre/api/LdapPrincipal.html#LdapPrincipal">LdapPrincipal ldapPrincipal = new LdapPrincipal( getAdminSession().getDirectoryService()
180 .getSchemaManager(),
181 dn, AuthenticationLevel.STRONG );
182 getLdapSession().putSaslProperty( SaslConstants.SASL_AUTHENT_USER, ldapPrincipal );
183 getLdapSession()
184 .putSaslProperty( Context.SECURITY_PRINCIPAL, getBindRequest().getName() );
185 }
186 catch ( Exception e )
187 {
188 throw new SaslException( I18n.err( I18n.ERR_669 ), e );
189 }
190
191 if ( !result )
192 {
193 throw new SaslException( I18n.err( I18n.ERR_670 ) );
194 }
195
196 break;
197
198 case INITIALIZED:
199 case TYPE_2_SENT:
200 case COMPLETED:
201 default:
202 throw new IllegalStateException( "Unexpected negotiation state " + state );
203 }
204
205 responseSent();
206 return retval;
207 }
208
209
210
211
212
213 private CoreSession authenticate( String user, String password ) throws Exception
214 {
215 BindOperationContexti/interceptor/context/BindOperationContext.html#BindOperationContext">BindOperationContext bindContext = new BindOperationContext( getLdapSession().getCoreSession() );
216 bindContext.setDn( new Dn( user ) );
217 bindContext.setCredentials( Strings.getBytesUtf8( password ) );
218
219 getAdminSession().getDirectoryService().getOperationManager().bind( bindContext );
220
221 return bindContext.getSession();
222 }
223
224
225
226
227
228 public boolean isComplete()
229 {
230 return state == NegotiationState.COMPLETED;
231 }
232 }