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.kerberos.shared.replay;
21
22
23 import java.io.Serializable;
24 import java.time.Duration;
25
26 import javax.security.auth.kerberos.KerberosPrincipal;
27
28 import org.apache.directory.shared.kerberos.KerberosTime;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 import com.github.benmanes.caffeine.cache.Cache;
33 import com.github.benmanes.caffeine.cache.Caffeine;
34
35
36
37
38
39
40
41
42
43
44
45 public class ReplayCacheImpl implements ReplayCache
46 {
47
48 private static final Logger LOG = LoggerFactory.getLogger( ReplayCacheImpl.class );
49
50
51 Cache<String, Object> cache;
52
53
54 private static final long DEFAULT_CLOCK_SKEW = 5L * KerberosTime.MINUTE;
55
56
57 private long clockSkew = DEFAULT_CLOCK_SKEW;
58
59
60
61
62 public static class ReplayCacheEntry implements Serializable
63 {
64 private static final long serialVersionUID = 1L;
65
66
67 private KerberosPrincipal serverPrincipal;
68
69
70 private KerberosPrincipal clientPrincipal;
71
72
73 private KerberosTime clientTime;
74
75
76 private int clientMicroSeconds;
77
78
79
80
81
82
83
84
85
86
87 public ReplayCacheEntry( KerberosPrincipal serverPrincipal, KerberosPrincipal clientPrincipal,
88 KerberosTime clientTime, int clientMicroSeconds )
89 {
90 this.serverPrincipal = serverPrincipal;
91 this.clientPrincipal = clientPrincipal;
92 this.clientTime = clientTime;
93 this.clientMicroSeconds = clientMicroSeconds;
94 }
95
96
97
98
99
100
101
102
103
104
105 public boolean equals( ReplayCacheEntry that )
106 {
107 return serverPrincipal.equals( that.serverPrincipal ) && clientPrincipal.equals( that.clientPrincipal )
108 && clientTime.equals( that.clientTime ) && clientMicroSeconds == that.clientMicroSeconds;
109 }
110
111
112
113
114
115
116
117
118 public boolean isOutsideClockSkew( long clockSkew )
119 {
120 return !clientTime.isInClockSkew( clockSkew );
121 }
122
123
124
125
126
127 private String createKey()
128 {
129 StringBuilder sb = new StringBuilder();
130 sb.append( ( clientPrincipal == null ) ? "null" : clientPrincipal.getName() );
131 sb.append( '#' );
132 sb.append( ( serverPrincipal == null ) ? "null" : serverPrincipal.getName() );
133 sb.append( '#' );
134 sb.append( ( clientTime == null ) ? "null" : clientTime.getDate() );
135 sb.append( '#' );
136 sb.append( clientMicroSeconds );
137
138 return sb.toString();
139 }
140 }
141
142
143
144
145
146
147
148
149
150 public ReplayCacheImpl( long clockSkew )
151 {
152 this.clockSkew = clockSkew;
153 this.cache = Caffeine.newBuilder().expireAfterWrite( Duration.ofMillis( clockSkew )).build();
154 }
155
156
157
158
159
160 public synchronized boolean isReplay( KerberosPrincipal serverPrincipal, KerberosPrincipal clientPrincipal,
161 KerberosTime clientTime, int clientMicroSeconds )
162 {
163 ReplayCacheEntry entry = new ReplayCacheEntry( serverPrincipal,
164 clientPrincipal, clientTime, clientMicroSeconds );
165 ReplayCacheEntry found = ( ReplayCacheEntry ) cache.getIfPresent( entry.createKey() );
166
167 if ( found == null )
168 {
169 return false;
170 }
171
172 entry = found;
173
174 return serverPrincipal.equals( entry.serverPrincipal ) &&
175 clientTime.equals( entry.clientTime ) &&
176 ( clientMicroSeconds == entry.clientMicroSeconds );
177 }
178
179
180
181
182
183
184 public synchronized void save( KerberosPrincipal serverPrincipal, KerberosPrincipal clientPrincipal,
185 KerberosTime clientTime, int clientMicroSeconds )
186 {
187 ReplayCacheEntry entry = new ReplayCacheEntry( serverPrincipal, clientPrincipal, clientTime, clientMicroSeconds );
188
189 cache.put( entry.createKey(), entry );
190 }
191
192
193
194
195
196 public void clear()
197 {
198 LOG.debug( "removing all the elements from cache" );
199 cache.invalidateAll();
200 }
201 }