KerberosTicket.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package javax.security.auth.kerberos;
  18. import java.io.Serializable;
  19. import java.net.InetAddress;
  20. import java.util.Arrays;
  21. import java.util.Date;
  22. import javax.crypto.SecretKey;
  23. import javax.security.auth.DestroyFailedException;
  24. import javax.security.auth.Destroyable;
  25. import javax.security.auth.RefreshFailedException;
  26. import javax.security.auth.Refreshable;
  27. import org.apache.harmony.auth.internal.kerberos.v5.KerberosException;
  28. import org.apache.harmony.auth.internal.kerberos.v5.KrbClient;
  29. import org.apache.harmony.auth.internal.nls.Messages;
  30. import org.apache.harmony.security.utils.Array;
  31. public class KerberosTicket implements Destroyable, Refreshable, Serializable {
  32. private static final long serialVersionUID = 7395334370157380539L;
  33. // The description of these flags defines in the Kerberos Protocol Specification (RFC 1510).
  34. // FORWARDABLE flag
  35. private static final int FORWARDABLE = 1;
  36. // FORWARDED flag
  37. private static final int FORWARDED = 2;
  38. // PROXIABLE flag
  39. private static final int PROXIABLE = 3;
  40. // PROXY flag
  41. private static final int PROXY = 4;
  42. // POSTDATED flag
  43. private static final int POSTDATED = 6;
  44. // RENEWABLE flag
  45. private static final int RENEWABLE = 8;
  46. // INITIAL flag
  47. private static final int INITIAL = 9;
  48. // number of flags used by Kerberos protocol
  49. private static final int FLAGS_NUM = 32;
  50. // line feed
  51. private static final String LF = "\n"; //$NON-NLS-1$
  52. //ASN.1 encoding of the ticket
  53. private byte[] asn1Encoding;
  54. //raw bytes for the session key
  55. private KeyImpl sessionKey;
  56. //ticket flags
  57. private boolean[] flags;
  58. //time of initial authentication for the client
  59. private Date authTime;
  60. //time after which the ticket will be valid
  61. private Date startTime;
  62. // time after which the ticket will be invalid
  63. private Date endTime;
  64. // expiration time for the ticket
  65. private Date renewTill;
  66. // client that owns this ticket
  67. private KerberosPrincipal client;
  68. //service that owns this ticket
  69. private KerberosPrincipal server;
  70. //addresses from where the ticket may be used by the client
  71. private InetAddress[] clientAddresses;
  72. // indicates the ticket state
  73. private transient boolean destroyed;
  74. public KerberosTicket(byte[] asn1Encoding, KerberosPrincipal client,
  75. KerberosPrincipal server, byte[] keyBytes, int keyType, boolean[] flags,
  76. Date authTime, Date startTime, Date endTime, Date renewTill,
  77. InetAddress[] clientAddresses) {
  78. if (asn1Encoding == null) {
  79. throw new IllegalArgumentException(Messages.getString("auth.3B")); //$NON-NLS-1$
  80. }
  81. if (client == null) {
  82. throw new IllegalArgumentException(Messages.getString("auth.3C")); //$NON-NLS-1$
  83. }
  84. if (server == null) {
  85. throw new IllegalArgumentException(Messages.getString("auth.3D")); //$NON-NLS-1$
  86. }
  87. if (keyBytes == null) {
  88. throw new IllegalArgumentException(Messages.getString("auth.3E")); //$NON-NLS-1$
  89. }
  90. if (authTime == null) {
  91. throw new IllegalArgumentException(Messages.getString("auth.3F")); //$NON-NLS-1$
  92. }
  93. if (endTime == null) {
  94. throw new IllegalArgumentException(Messages.getString("auth.40")); //$NON-NLS-1$
  95. }
  96. this.asn1Encoding = new byte[asn1Encoding.length];
  97. System.arraycopy(asn1Encoding, 0, this.asn1Encoding, 0, this.asn1Encoding.length);
  98. this.client = client;
  99. this.server = server;
  100. this.sessionKey = new KeyImpl(keyBytes, keyType);
  101. if (flags == null) {
  102. this.flags = new boolean[FLAGS_NUM];
  103. } else if (flags.length > FLAGS_NUM) {
  104. this.flags = new boolean[flags.length];
  105. System.arraycopy(flags, 0, this.flags, 0, this.flags.length);
  106. } else {
  107. this.flags = new boolean[FLAGS_NUM];
  108. System.arraycopy(flags, 0, this.flags, 0, flags.length);
  109. }
  110. if (this.flags[RENEWABLE] && renewTill == null) {
  111. throw new IllegalArgumentException(Messages.getString("auth.41")); //$NON-NLS-1$
  112. }
  113. this.renewTill = renewTill;
  114. if (startTime != null) {
  115. this.startTime = startTime;
  116. } else {
  117. this.startTime = authTime;
  118. }
  119. if (this.startTime.getTime() > endTime.getTime()) {
  120. // TODO: make correct description of the exception
  121. throw new IllegalArgumentException(Messages.getString("auth.42")); //$NON-NLS-1$
  122. }
  123. this.authTime = authTime;
  124. this.endTime = endTime;
  125. if (clientAddresses != null) {
  126. this.clientAddresses = new InetAddress[clientAddresses.length];
  127. System.arraycopy(clientAddresses, 0, this.clientAddresses, 0,
  128. this.clientAddresses.length);
  129. }
  130. }
  131. public final KerberosPrincipal getClient() {
  132. return client;
  133. }
  134. public final KerberosPrincipal getServer() {
  135. return server;
  136. }
  137. public final SecretKey getSessionKey() {
  138. checkState();
  139. return sessionKey;
  140. }
  141. public final int getSessionKeyType() {
  142. checkState();
  143. return sessionKey.getKeyType();
  144. }
  145. public final byte[] getEncoded() {
  146. checkState();
  147. byte[] tmp = new byte[this.asn1Encoding.length];
  148. System.arraycopy(this.asn1Encoding, 0, tmp, 0, tmp.length);
  149. return tmp;
  150. }
  151. public final boolean isForwardable() {
  152. checkState();
  153. return flags[FORWARDABLE];
  154. }
  155. public final boolean isForwarded() {
  156. checkState();
  157. //TODO: was based on authentication involving a forwarded TGT ?
  158. return flags[FORWARDED];
  159. }
  160. public final boolean isProxiable() {
  161. checkState();
  162. return flags[PROXIABLE];
  163. }
  164. public final boolean isProxy() {
  165. checkState();
  166. return flags[PROXY];
  167. }
  168. public final boolean isPostdated() {
  169. checkState();
  170. return flags[POSTDATED];
  171. }
  172. public final boolean isRenewable() {
  173. checkState();
  174. return flags[RENEWABLE];
  175. }
  176. public final boolean isInitial() {
  177. checkState();
  178. return flags[INITIAL];
  179. }
  180. public final boolean[] getFlags() {
  181. if (destroyed) {
  182. return null;
  183. }
  184. boolean[] tmp = new boolean[flags.length];
  185. System.arraycopy(flags, 0, tmp, 0, tmp.length);
  186. return tmp;
  187. }
  188. public final Date getAuthTime() {
  189. if (destroyed) {
  190. return null;
  191. }
  192. return new Date(authTime.getTime());
  193. }
  194. public final Date getStartTime() {
  195. checkState();
  196. return new Date(startTime.getTime());
  197. }
  198. public final Date getEndTime() {
  199. if (destroyed) {
  200. return null;
  201. }
  202. return new Date(endTime.getTime());
  203. }
  204. public final Date getRenewTill() {
  205. if (destroyed) {
  206. return null;
  207. }
  208. return renewTill;
  209. }
  210. public final InetAddress[] getClientAddresses() {
  211. if (this.clientAddresses != null) {
  212. InetAddress[] tmp = new InetAddress[this.clientAddresses.length];
  213. System.arraycopy(clientAddresses, 0, tmp, 0, tmp.length);
  214. return tmp;
  215. }
  216. return null;
  217. }
  218. public void destroy() throws DestroyFailedException {
  219. if (destroyed) {
  220. return;
  221. }
  222. Arrays.fill(this.asn1Encoding, (byte) 0);
  223. this.client = null;
  224. this.server = null;
  225. this.sessionKey.destroy();
  226. this.flags = null;
  227. this.authTime = null;
  228. this.startTime = null;
  229. this.endTime = null;
  230. this.renewTill = null;
  231. this.clientAddresses = null;
  232. destroyed = true;
  233. }
  234. public boolean isDestroyed() {
  235. return destroyed;
  236. }
  237. public void refresh() throws RefreshFailedException {
  238. checkState();
  239. if (!flags[RENEWABLE]) {
  240. throw new RefreshFailedException(Messages.getString("auth.44")); //$NON-NLS-1$
  241. }
  242. if (System.currentTimeMillis() > this.renewTill.getTime()) {
  243. throw new RefreshFailedException(Messages.getString("auth.45")); //$NON-NLS-1$
  244. }
  245. try {
  246. KrbClient.doTGS();
  247. } catch (KerberosException e) {
  248. throw new RefreshFailedException(e.getMessage());
  249. }
  250. }
  251. public boolean isCurrent() {
  252. checkState();
  253. if (this.getStartTime().getTime() <= System.currentTimeMillis()
  254. && System.currentTimeMillis() <= this.getEndTime().getTime()) {
  255. return true;
  256. }
  257. return false;
  258. }
  259. @Override
  260. public String toString() {
  261. checkState();
  262. StringBuilder sb = new StringBuilder();
  263. sb.append("Ticket = ").append(Array.toString(asn1Encoding, "(hex) ") + LF); //$NON-NLS-1$ //$NON-NLS-2$
  264. sb.append("Client Principal = ").append(client.getName() + LF); //$NON-NLS-1$
  265. sb.append("Server Principal = ").append(server.getName() + LF); //$NON-NLS-1$
  266. //TODO: append session key
  267. sb.append("Session Key = ").append(sessionKey.toString() + LF); //$NON-NLS-1$
  268. sb.append("Forwardable Ticket = ").append(flags[FORWARDABLE] + LF); //$NON-NLS-1$
  269. sb.append("Forwarded Ticket = ").append(flags[FORWARDED] + LF); //$NON-NLS-1$
  270. sb.append("Proxiable Ticket = ").append(flags[PROXIABLE] + LF); //$NON-NLS-1$
  271. sb.append("Proxy Ticket = ").append(flags[PROXY] + LF); //$NON-NLS-1$
  272. sb.append("Postdated Ticket = ").append(flags[POSTDATED] + LF); //$NON-NLS-1$
  273. sb.append("Renewable Ticket = ").append(flags[RENEWABLE] + LF); //$NON-NLS-1$
  274. sb.append("Initial Ticket = ").append(flags[INITIAL] + LF); //$NON-NLS-1$
  275. sb.append("Auth Time = ").append(this.authTime.toString() + LF); //$NON-NLS-1$
  276. sb.append("Start Time = ").append(this.startTime.toString() + LF); //$NON-NLS-1$
  277. sb.append("End Time = ").append(this.endTime.toString() + LF); //$NON-NLS-1$
  278. sb.append("Renew Till = ").append(this.renewTill.toString() + LF); //$NON-NLS-1$
  279. sb.append("Client Addresses "); //$NON-NLS-1$
  280. if (clientAddresses != null) {
  281. for (int i = 0; i < clientAddresses.length; i++) {
  282. if (clientAddresses[i] == null) {
  283. throw new NullPointerException(Messages.getString("auth.46")); //$NON-NLS-1$
  284. }
  285. sb
  286. .append("clientAddresses[" + i + "] = ").append(clientAddresses[i].toString() + LF + "\t\t"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
  287. }
  288. } else {
  289. sb.append("null"); //$NON-NLS-1$
  290. }
  291. return sb.toString();
  292. }
  293. /**
  294. * if a key is destroyed then IllegalStateException must be thrown
  295. */
  296. private void checkState() {
  297. if (destroyed) {
  298. throw new IllegalStateException(Messages.getString("auth.43")); //$NON-NLS-1$
  299. }
  300. }
  301. }