Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/javax/security/auth/kerberos/KerberosTicket.java
38918 views
1
/*
2
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package javax.security.auth.kerberos;
27
28
import java.io.*;
29
import java.util.Date;
30
import java.util.Arrays;
31
import java.net.InetAddress;
32
import java.util.Objects;
33
import javax.crypto.SecretKey;
34
import javax.security.auth.Refreshable;
35
import javax.security.auth.Destroyable;
36
import javax.security.auth.RefreshFailedException;
37
import javax.security.auth.DestroyFailedException;
38
39
import sun.misc.HexDumpEncoder;
40
import sun.security.krb5.EncryptionKey;
41
import sun.security.krb5.Asn1Exception;
42
import sun.security.util.*;
43
44
/**
45
* This class encapsulates a Kerberos ticket and associated
46
* information as viewed from the client's point of view. It captures all
47
* information that the Key Distribution Center (KDC) sends to the client
48
* in the reply message KDC-REP defined in the Kerberos Protocol
49
* Specification (<a href=http://www.ietf.org/rfc/rfc4120.txt>RFC 4120</a>).
50
* <p>
51
* All Kerberos JAAS login modules that authenticate a user to a KDC should
52
* use this class. Where available, the login module might even read this
53
* information from a ticket cache in the operating system instead of
54
* directly communicating with the KDC. During the commit phase of the JAAS
55
* authentication process, the JAAS login module should instantiate this
56
* class and store the instance in the private credential set of a
57
* {@link javax.security.auth.Subject Subject}.<p>
58
*
59
* It might be necessary for the application to be granted a
60
* {@link javax.security.auth.PrivateCredentialPermission
61
* PrivateCredentialPermission} if it needs to access a KerberosTicket
62
* instance from a Subject. This permission is not needed when the
63
* application depends on the default JGSS Kerberos mechanism to access the
64
* KerberosTicket. In that case, however, the application will need an
65
* appropriate
66
* {@link javax.security.auth.kerberos.ServicePermission ServicePermission}.
67
* <p>
68
* Note that this class is applicable to both ticket granting tickets and
69
* other regular service tickets. A ticket granting ticket is just a
70
* special case of a more generalized service ticket.
71
*
72
* @see javax.security.auth.Subject
73
* @see javax.security.auth.PrivateCredentialPermission
74
* @see javax.security.auth.login.LoginContext
75
* @see org.ietf.jgss.GSSCredential
76
* @see org.ietf.jgss.GSSManager
77
*
78
* @author Mayank Upadhyay
79
* @since 1.4
80
*/
81
public class KerberosTicket implements Destroyable, Refreshable,
82
java.io.Serializable {
83
84
private static final long serialVersionUID = 7395334370157380539L;
85
86
// XXX Make these flag indices public
87
private static final int FORWARDABLE_TICKET_FLAG = 1;
88
private static final int FORWARDED_TICKET_FLAG = 2;
89
private static final int PROXIABLE_TICKET_FLAG = 3;
90
private static final int PROXY_TICKET_FLAG = 4;
91
private static final int POSTDATED_TICKET_FLAG = 6;
92
private static final int RENEWABLE_TICKET_FLAG = 8;
93
private static final int INITIAL_TICKET_FLAG = 9;
94
95
private static final int NUM_FLAGS = 32;
96
97
/**
98
*
99
* ASN.1 DER Encoding of the Ticket as defined in the
100
* Kerberos Protocol Specification RFC4120.
101
*
102
* @serial
103
*/
104
105
private byte[] asn1Encoding;
106
107
/**
108
*{@code KeyImpl} is serialized by writing out the ASN1 Encoded bytes
109
* of the encryption key. The ASN1 encoding is defined in RFC4120 and as
110
* follows:
111
* <pre>
112
* EncryptionKey ::= SEQUENCE {
113
* keytype [0] Int32 -- actually encryption type --,
114
* keyvalue [1] OCTET STRING
115
* }
116
* </pre>
117
*
118
* @serial
119
*/
120
121
private KeyImpl sessionKey;
122
123
/**
124
*
125
* Ticket Flags as defined in the Kerberos Protocol Specification RFC4120.
126
*
127
* @serial
128
*/
129
130
private boolean[] flags;
131
132
/**
133
*
134
* Time of initial authentication
135
*
136
* @serial
137
*/
138
139
private Date authTime;
140
141
/**
142
*
143
* Time after which the ticket is valid.
144
* @serial
145
*/
146
private Date startTime;
147
148
/**
149
*
150
* Time after which the ticket will not be honored. (its expiration time).
151
*
152
* @serial
153
*/
154
155
private Date endTime;
156
157
/**
158
*
159
* For renewable Tickets it indicates the maximum endtime that may be
160
* included in a renewal. It can be thought of as the absolute expiration
161
* time for the ticket, including all renewals. This field may be null
162
* for tickets that are not renewable.
163
*
164
* @serial
165
*/
166
167
private Date renewTill;
168
169
/**
170
*
171
* Client that owns the service ticket
172
*
173
* @serial
174
*/
175
176
private KerberosPrincipal client;
177
178
/**
179
*
180
* The service for which the ticket was issued.
181
*
182
* @serial
183
*/
184
185
private KerberosPrincipal server;
186
187
/**
188
*
189
* The addresses from where the ticket may be used by the client.
190
* This field may be null when the ticket is usable from any address.
191
*
192
* @serial
193
*/
194
195
private InetAddress[] clientAddresses;
196
197
transient KerberosPrincipal clientAlias = null;
198
199
transient KerberosPrincipal serverAlias = null;
200
201
/**
202
* Evidence ticket if proxy_impersonator. This field can be accessed
203
* by KerberosSecrets. It's serialized.
204
*/
205
KerberosTicket proxy = null;
206
207
private transient boolean destroyed = false;
208
209
/**
210
* Constructs a KerberosTicket using credentials information that a
211
* client either receives from a KDC or reads from a cache.
212
*
213
* @param asn1Encoding the ASN.1 encoding of the ticket as defined by
214
* the Kerberos protocol specification.
215
* @param client the client that owns this service
216
* ticket
217
* @param server the service that this ticket is for
218
* @param sessionKey the raw bytes for the session key that must be
219
* used to encrypt the authenticator that will be sent to the server
220
* @param keyType the key type for the session key as defined by the
221
* Kerberos protocol specification.
222
* @param flags the ticket flags. Each element in this array indicates
223
* the value for the corresponding bit in the ASN.1 BitString that
224
* represents the ticket flags. If the number of elements in this array
225
* is less than the number of flags used by the Kerberos protocol,
226
* then the missing flags will be filled in with false.
227
* @param authTime the time of initial authentication for the client
228
* @param startTime the time after which the ticket will be valid. This
229
* may be null in which case the value of authTime is treated as the
230
* startTime.
231
* @param endTime the time after which the ticket will no longer be
232
* valid
233
* @param renewTill an absolute expiration time for the ticket,
234
* including all renewal that might be possible. This field may be null
235
* for tickets that are not renewable.
236
* @param clientAddresses the addresses from where the ticket may be
237
* used by the client. This field may be null when the ticket is usable
238
* from any address.
239
*/
240
public KerberosTicket(byte[] asn1Encoding,
241
KerberosPrincipal client,
242
KerberosPrincipal server,
243
byte[] sessionKey,
244
int keyType,
245
boolean[] flags,
246
Date authTime,
247
Date startTime,
248
Date endTime,
249
Date renewTill,
250
InetAddress[] clientAddresses) {
251
252
init(asn1Encoding, client, server, sessionKey, keyType, flags,
253
authTime, startTime, endTime, renewTill, clientAddresses);
254
}
255
256
private void init(byte[] asn1Encoding,
257
KerberosPrincipal client,
258
KerberosPrincipal server,
259
byte[] sessionKey,
260
int keyType,
261
boolean[] flags,
262
Date authTime,
263
Date startTime,
264
Date endTime,
265
Date renewTill,
266
InetAddress[] clientAddresses) {
267
if (sessionKey == null)
268
throw new IllegalArgumentException("Session key for ticket"
269
+ " cannot be null");
270
init(asn1Encoding, client, server,
271
new KeyImpl(sessionKey, keyType), flags, authTime,
272
startTime, endTime, renewTill, clientAddresses);
273
}
274
275
private void init(byte[] asn1Encoding,
276
KerberosPrincipal client,
277
KerberosPrincipal server,
278
KeyImpl sessionKey,
279
boolean[] flags,
280
Date authTime,
281
Date startTime,
282
Date endTime,
283
Date renewTill,
284
InetAddress[] clientAddresses) {
285
if (asn1Encoding == null)
286
throw new IllegalArgumentException("ASN.1 encoding of ticket"
287
+ " cannot be null");
288
this.asn1Encoding = asn1Encoding.clone();
289
290
if (client == null)
291
throw new IllegalArgumentException("Client name in ticket"
292
+ " cannot be null");
293
this.client = client;
294
295
if (server == null)
296
throw new IllegalArgumentException("Server name in ticket"
297
+ " cannot be null");
298
this.server = server;
299
300
// Caller needs to make sure `sessionKey` will not be null
301
this.sessionKey = sessionKey;
302
303
if (flags != null) {
304
if (flags.length >= NUM_FLAGS)
305
this.flags = flags.clone();
306
else {
307
this.flags = new boolean[NUM_FLAGS];
308
// Fill in whatever we have
309
for (int i = 0; i < flags.length; i++)
310
this.flags[i] = flags[i];
311
}
312
} else
313
this.flags = new boolean[NUM_FLAGS];
314
315
if (this.flags[RENEWABLE_TICKET_FLAG] && renewTill != null) {
316
this.renewTill = new Date(renewTill.getTime());
317
}
318
319
if (authTime != null) {
320
this.authTime = new Date(authTime.getTime());
321
}
322
if (startTime != null) {
323
this.startTime = new Date(startTime.getTime());
324
} else {
325
this.startTime = this.authTime;
326
}
327
328
if (endTime == null)
329
throw new IllegalArgumentException("End time for ticket validity"
330
+ " cannot be null");
331
this.endTime = new Date(endTime.getTime());
332
333
if (clientAddresses != null)
334
this.clientAddresses = clientAddresses.clone();
335
}
336
337
/**
338
* Returns the client principal associated with this ticket.
339
*
340
* @return the client principal.
341
*/
342
public final KerberosPrincipal getClient() {
343
return client;
344
}
345
346
/**
347
* Returns the service principal associated with this ticket.
348
*
349
* @return the service principal.
350
*/
351
public final KerberosPrincipal getServer() {
352
return server;
353
}
354
355
/**
356
* Returns the session key associated with this ticket.
357
*
358
* @return the session key.
359
*/
360
public final SecretKey getSessionKey() {
361
if (destroyed)
362
throw new IllegalStateException("This ticket is no longer valid");
363
return sessionKey;
364
}
365
366
/**
367
* Returns the key type of the session key associated with this
368
* ticket as defined by the Kerberos Protocol Specification.
369
*
370
* @return the key type of the session key associated with this
371
* ticket.
372
*
373
* @see #getSessionKey()
374
*/
375
public final int getSessionKeyType() {
376
if (destroyed)
377
throw new IllegalStateException("This ticket is no longer valid");
378
return sessionKey.getKeyType();
379
}
380
381
/**
382
* Determines if this ticket is forwardable.
383
*
384
* @return true if this ticket is forwardable, false if not.
385
*/
386
public final boolean isForwardable() {
387
return flags == null? false: flags[FORWARDABLE_TICKET_FLAG];
388
}
389
390
/**
391
* Determines if this ticket had been forwarded or was issued based on
392
* authentication involving a forwarded ticket-granting ticket.
393
*
394
* @return true if this ticket had been forwarded or was issued based on
395
* authentication involving a forwarded ticket-granting ticket,
396
* false otherwise.
397
*/
398
public final boolean isForwarded() {
399
return flags == null? false: flags[FORWARDED_TICKET_FLAG];
400
}
401
402
/**
403
* Determines if this ticket is proxiable.
404
*
405
* @return true if this ticket is proxiable, false if not.
406
*/
407
public final boolean isProxiable() {
408
return flags == null? false: flags[PROXIABLE_TICKET_FLAG];
409
}
410
411
/**
412
* Determines is this ticket is a proxy-ticket.
413
*
414
* @return true if this ticket is a proxy-ticket, false if not.
415
*/
416
public final boolean isProxy() {
417
return flags == null? false: flags[PROXY_TICKET_FLAG];
418
}
419
420
421
/**
422
* Determines is this ticket is post-dated.
423
*
424
* @return true if this ticket is post-dated, false if not.
425
*/
426
public final boolean isPostdated() {
427
return flags == null? false: flags[POSTDATED_TICKET_FLAG];
428
}
429
430
/**
431
* Determines is this ticket is renewable. If so, the {@link #refresh()
432
* refresh} method can be called, assuming the validity period for
433
* renewing is not already over.
434
*
435
* @return true if this ticket is renewable, false if not.
436
*/
437
public final boolean isRenewable() {
438
return flags == null? false: flags[RENEWABLE_TICKET_FLAG];
439
}
440
441
/**
442
* Determines if this ticket was issued using the Kerberos AS-Exchange
443
* protocol, and not issued based on some ticket-granting ticket.
444
*
445
* @return true if this ticket was issued using the Kerberos AS-Exchange
446
* protocol, false if not.
447
*/
448
public final boolean isInitial() {
449
return flags == null? false: flags[INITIAL_TICKET_FLAG];
450
}
451
452
/**
453
* Returns the flags associated with this ticket. Each element in the
454
* returned array indicates the value for the corresponding bit in the
455
* ASN.1 BitString that represents the ticket flags.
456
*
457
* @return the flags associated with this ticket.
458
*/
459
public final boolean[] getFlags() {
460
return (flags == null? null: flags.clone());
461
}
462
463
/**
464
* Returns the time that the client was authenticated.
465
*
466
* @return the time that the client was authenticated
467
* or null if not set.
468
*/
469
public final java.util.Date getAuthTime() {
470
return (authTime == null) ? null : (Date)authTime.clone();
471
}
472
473
/**
474
* Returns the start time for this ticket's validity period.
475
*
476
* @return the start time for this ticket's validity period
477
* or null if not set.
478
*/
479
public final java.util.Date getStartTime() {
480
return (startTime == null) ? null : (Date)startTime.clone();
481
}
482
483
/**
484
* Returns the expiration time for this ticket's validity period.
485
*
486
* @return the expiration time for this ticket's validity period.
487
*/
488
public final java.util.Date getEndTime() {
489
return (endTime == null) ? null : (Date) endTime.clone();
490
}
491
492
/**
493
* Returns the latest expiration time for this ticket, including all
494
* renewals. This will return a null value for non-renewable tickets.
495
*
496
* @return the latest expiration time for this ticket.
497
*/
498
public final java.util.Date getRenewTill() {
499
return (renewTill == null) ? null: (Date)renewTill.clone();
500
}
501
502
/**
503
* Returns a list of addresses from where the ticket can be used.
504
*
505
* @return ths list of addresses or null, if the field was not
506
* provided.
507
*/
508
public final java.net.InetAddress[] getClientAddresses() {
509
return (clientAddresses == null) ? null: clientAddresses.clone();
510
}
511
512
/**
513
* Returns an ASN.1 encoding of the entire ticket.
514
*
515
* @return an ASN.1 encoding of the entire ticket.
516
*/
517
public final byte[] getEncoded() {
518
if (destroyed)
519
throw new IllegalStateException("This ticket is no longer valid");
520
return asn1Encoding.clone();
521
}
522
523
/** Determines if this ticket is still current. */
524
public boolean isCurrent() {
525
return endTime == null? false: (System.currentTimeMillis() <= endTime.getTime());
526
}
527
528
/**
529
* Extends the validity period of this ticket. The ticket will contain
530
* a new session key if the refresh operation succeeds. The refresh
531
* operation will fail if the ticket is not renewable or the latest
532
* allowable renew time has passed. Any other error returned by the
533
* KDC will also cause this method to fail.
534
*
535
* Note: This method is not synchronized with the the accessor
536
* methods of this object. Hence callers need to be aware of multiple
537
* threads that might access this and try to renew it at the same
538
* time.
539
*
540
* @throws RefreshFailedException if the ticket is not renewable, or
541
* the latest allowable renew time has passed, or the KDC returns some
542
* error.
543
*
544
* @see #isRenewable()
545
* @see #getRenewTill()
546
*/
547
public void refresh() throws RefreshFailedException {
548
549
if (destroyed)
550
throw new RefreshFailedException("A destroyed ticket "
551
+ "cannot be renewd.");
552
553
if (!isRenewable())
554
throw new RefreshFailedException("This ticket is not renewable");
555
556
if (getRenewTill() == null) {
557
// Renewable ticket without renew-till. Illegal and ignored.
558
return;
559
}
560
561
if (System.currentTimeMillis() > getRenewTill().getTime())
562
throw new RefreshFailedException("This ticket is past "
563
+ "its last renewal time.");
564
Throwable e = null;
565
sun.security.krb5.Credentials krb5Creds = null;
566
567
try {
568
krb5Creds = new sun.security.krb5.Credentials(asn1Encoding,
569
client.toString(),
570
(clientAlias != null ?
571
clientAlias.getName() : null),
572
server.toString(),
573
(serverAlias != null ?
574
serverAlias.getName() : null),
575
sessionKey.getEncoded(),
576
sessionKey.getKeyType(),
577
flags,
578
authTime,
579
startTime,
580
endTime,
581
renewTill,
582
clientAddresses);
583
krb5Creds = krb5Creds.renew();
584
} catch (sun.security.krb5.KrbException krbException) {
585
e = krbException;
586
} catch (java.io.IOException ioException) {
587
e = ioException;
588
}
589
590
if (e != null) {
591
RefreshFailedException rfException
592
= new RefreshFailedException("Failed to renew Kerberos Ticket "
593
+ "for client " + client
594
+ " and server " + server
595
+ " - " + e.getMessage());
596
rfException.initCause(e);
597
throw rfException;
598
}
599
600
/*
601
* In case multiple threads try to refresh it at the same time.
602
*/
603
synchronized (this) {
604
try {
605
this.destroy();
606
} catch (DestroyFailedException dfException) {
607
// Squelch it since we don't care about the old ticket.
608
}
609
init(krb5Creds.getEncoded(),
610
new KerberosPrincipal(krb5Creds.getClient().getName()),
611
new KerberosPrincipal(krb5Creds.getServer().getName(),
612
KerberosPrincipal.KRB_NT_SRV_INST),
613
krb5Creds.getSessionKey().getBytes(),
614
krb5Creds.getSessionKey().getEType(),
615
krb5Creds.getFlags(),
616
krb5Creds.getAuthTime(),
617
krb5Creds.getStartTime(),
618
krb5Creds.getEndTime(),
619
krb5Creds.getRenewTill(),
620
krb5Creds.getClientAddresses());
621
destroyed = false;
622
}
623
}
624
625
/**
626
* Destroys the ticket and destroys any sensitive information stored in
627
* it.
628
*/
629
public void destroy() throws DestroyFailedException {
630
if (!destroyed) {
631
Arrays.fill(asn1Encoding, (byte) 0);
632
client = null;
633
server = null;
634
sessionKey.destroy();
635
flags = null;
636
authTime = null;
637
startTime = null;
638
endTime = null;
639
renewTill = null;
640
clientAddresses = null;
641
destroyed = true;
642
}
643
}
644
645
/**
646
* Determines if this ticket has been destroyed.
647
*/
648
public boolean isDestroyed() {
649
return destroyed;
650
}
651
652
public String toString() {
653
if (destroyed) {
654
return "Destroyed KerberosTicket";
655
}
656
StringBuffer caddrBuf = new StringBuffer();
657
if (clientAddresses != null) {
658
for (int i = 0; i < clientAddresses.length; i++) {
659
caddrBuf.append("clientAddresses[" + i + "] = " +
660
clientAddresses[i].toString());
661
}
662
}
663
return ("Ticket (hex) = " + "\n" +
664
(new HexDumpEncoder()).encodeBuffer(asn1Encoding) + "\n" +
665
"Client Principal = " + client.toString() + "\n" +
666
"Server Principal = " + server.toString() + "\n" +
667
"Session Key = " + sessionKey.toString() + "\n" +
668
"Forwardable Ticket " + flags[FORWARDABLE_TICKET_FLAG] + "\n" +
669
"Forwarded Ticket " + flags[FORWARDED_TICKET_FLAG] + "\n" +
670
"Proxiable Ticket " + flags[PROXIABLE_TICKET_FLAG] + "\n" +
671
"Proxy Ticket " + flags[PROXY_TICKET_FLAG] + "\n" +
672
"Postdated Ticket " + flags[POSTDATED_TICKET_FLAG] + "\n" +
673
"Renewable Ticket " + flags[RENEWABLE_TICKET_FLAG] + "\n" +
674
"Initial Ticket " + flags[RENEWABLE_TICKET_FLAG] + "\n" +
675
"Auth Time = " + String.valueOf(authTime) + "\n" +
676
"Start Time = " + String.valueOf(startTime) + "\n" +
677
"End Time = " + endTime.toString() + "\n" +
678
"Renew Till = " + String.valueOf(renewTill) + "\n" +
679
"Client Addresses " +
680
(clientAddresses == null ? " Null " : caddrBuf.toString() +
681
(proxy == null ? "" : "\nwith a proxy ticket") +
682
"\n"));
683
}
684
685
/**
686
* Returns a hashcode for this KerberosTicket.
687
*
688
* @return a hashCode() for the {@code KerberosTicket}
689
* @since 1.6
690
*/
691
public int hashCode() {
692
int result = 17;
693
if (isDestroyed()) {
694
return result;
695
}
696
result = result * 37 + Arrays.hashCode(getEncoded());
697
result = result * 37 + endTime.hashCode();
698
result = result * 37 + client.hashCode();
699
result = result * 37 + server.hashCode();
700
result = result * 37 + sessionKey.hashCode();
701
702
// authTime may be null
703
if (authTime != null) {
704
result = result * 37 + authTime.hashCode();
705
}
706
707
// startTime may be null
708
if (startTime != null) {
709
result = result * 37 + startTime.hashCode();
710
}
711
712
// renewTill may be null
713
if (renewTill != null) {
714
result = result * 37 + renewTill.hashCode();
715
}
716
717
// clientAddress may be null, the array's hashCode is 0
718
result = result * 37 + Arrays.hashCode(clientAddresses);
719
720
if (proxy != null) {
721
result = result * 37 + proxy.hashCode();
722
}
723
return result * 37 + Arrays.hashCode(flags);
724
}
725
726
/**
727
* Compares the specified Object with this KerberosTicket for equality.
728
* Returns true if the given object is also a
729
* {@code KerberosTicket} and the two
730
* {@code KerberosTicket} instances are equivalent.
731
*
732
* @param other the Object to compare to
733
* @return true if the specified object is equal to this KerberosTicket,
734
* false otherwise. NOTE: Returns false if either of the KerberosTicket
735
* objects has been destroyed.
736
* @since 1.6
737
*/
738
public boolean equals(Object other) {
739
740
if (other == this)
741
return true;
742
743
if (! (other instanceof KerberosTicket)) {
744
return false;
745
}
746
747
KerberosTicket otherTicket = ((KerberosTicket) other);
748
if (isDestroyed() || otherTicket.isDestroyed()) {
749
return false;
750
}
751
752
if (!Arrays.equals(getEncoded(), otherTicket.getEncoded()) ||
753
!endTime.equals(otherTicket.getEndTime()) ||
754
!server.equals(otherTicket.getServer()) ||
755
!client.equals(otherTicket.getClient()) ||
756
!sessionKey.equals(otherTicket.getSessionKey()) ||
757
!Arrays.equals(clientAddresses, otherTicket.getClientAddresses()) ||
758
!Arrays.equals(flags, otherTicket.getFlags())) {
759
return false;
760
}
761
762
// authTime may be null
763
if (authTime == null) {
764
if (otherTicket.getAuthTime() != null)
765
return false;
766
} else {
767
if (!authTime.equals(otherTicket.getAuthTime()))
768
return false;
769
}
770
771
// startTime may be null
772
if (startTime == null) {
773
if (otherTicket.getStartTime() != null)
774
return false;
775
} else {
776
if (!startTime.equals(otherTicket.getStartTime()))
777
return false;
778
}
779
780
if (renewTill == null) {
781
if (otherTicket.getRenewTill() != null)
782
return false;
783
} else {
784
if (!renewTill.equals(otherTicket.getRenewTill()))
785
return false;
786
}
787
788
if (!Objects.equals(proxy, otherTicket.proxy)) {
789
return false;
790
}
791
792
return true;
793
}
794
795
private void readObject(ObjectInputStream s)
796
throws IOException, ClassNotFoundException {
797
s.defaultReadObject();
798
if (sessionKey == null) {
799
throw new InvalidObjectException("Session key cannot be null");
800
}
801
try {
802
init(asn1Encoding, client, server, sessionKey,
803
flags, authTime, startTime, endTime,
804
renewTill, clientAddresses);
805
} catch (IllegalArgumentException iae) {
806
throw (InvalidObjectException)
807
new InvalidObjectException(iae.getMessage()).initCause(iae);
808
}
809
}
810
}
811
812