1 /*
2  * Copyright (c) 2000, 2013, 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 /*
27  *
28  *  (C) Copyright IBM Corp. 1999 All Rights Reserved.
29  *  Copyright 1997 The Open Group Research Institute.  All rights reserved.
30  */
31 
32 package sun.security.krb5;
33 
34 import sun.security.krb5.internal.*;
35 import sun.security.krb5.internal.crypto.KeyUsage;
36 import sun.security.util.*;
37 import java.io.IOException;
38 
39 /**
40  * This class encapsulates a KRB-AP-REP sent from the service to the
41  * client.
42  */
43 public class KrbApRep {
44     private byte[] obuf;
45     private byte[] ibuf;
46     private EncAPRepPart encPart; // although in plain text
47     private APRep apRepMessg;
48 
49     /**
50      * Constructs a KRB-AP-REP to send to a client.
51      * @throws KrbException
52      * @throws IOException
53      */
54      // Used in AcceptSecContextToken
KrbApRep(KrbApReq incomingReq, boolean useSeqNumber, EncryptionKey subKey)55     public KrbApRep(KrbApReq incomingReq,
56                      boolean useSeqNumber,
57                      EncryptionKey subKey)
58             throws KrbException, IOException {
59 
60         SeqNumber seqNum = new LocalSeqNumber();
61 
62         init(incomingReq, subKey, seqNum);
63     }
64 
65     /**
66      * Constructs a KRB-AP-REQ from the bytes received from a service.
67      * @throws KrbException
68      * @throws IOException
69      */
70      // Used in AcceptSecContextToken
KrbApRep(byte[] message, Credentials tgtCreds, KrbApReq outgoingReq)71     public KrbApRep(byte[] message, Credentials tgtCreds,
72                     KrbApReq outgoingReq) throws KrbException, IOException {
73         this(message, tgtCreds);
74         authenticate(outgoingReq);
75     }
76 
init(KrbApReq apReq, EncryptionKey subKey, SeqNumber seqNumber)77     private void init(KrbApReq apReq,
78               EncryptionKey subKey,
79         SeqNumber seqNumber)
80         throws KrbException, IOException {
81         createMessage(
82                       apReq.getCreds().key,
83                       apReq.getCtime(),
84                       apReq.cusec(),
85                       subKey,
86                       seqNumber);
87         obuf = apRepMessg.asn1Encode();
88     }
89 
90 
91     /**
92      * Constructs a KrbApRep object.
93      * @param msg a byte array of reply message.
94      * @param tgs_creds client's credential.
95      * @exception KrbException
96      * @exception IOException
97      */
KrbApRep(byte[] msg, Credentials tgs_creds)98     private KrbApRep(byte[] msg, Credentials tgs_creds)
99         throws KrbException, IOException {
100         this(new DerValue(msg), tgs_creds);
101     }
102 
103     /**
104      * Constructs a KrbApRep object.
105      * @param msg a byte array of reply message.
106      * @param tgs_creds client's credential.
107      * @exception KrbException
108      * @exception IOException
109      */
KrbApRep(DerValue encoding, Credentials tgs_creds)110     private KrbApRep(DerValue encoding, Credentials tgs_creds)
111         throws KrbException, IOException {
112         APRep rep = null;
113         try {
114             rep = new APRep(encoding);
115         } catch (Asn1Exception e) {
116             rep = null;
117             KRBError err = new KRBError(encoding);
118             String errStr = err.getErrorString();
119             String eText;
120             if (errStr.charAt(errStr.length() - 1) == 0)
121                 eText = errStr.substring(0, errStr.length() - 1);
122             else
123                 eText = errStr;
124             KrbException ke = new KrbException(err.getErrorCode(), eText);
125             ke.initCause(e);
126             throw ke;
127         }
128 
129         byte[] temp = rep.encPart.decrypt(tgs_creds.key,
130             KeyUsage.KU_ENC_AP_REP_PART);
131         byte[] enc_ap_rep_part = rep.encPart.reset(temp);
132 
133         encoding = new DerValue(enc_ap_rep_part);
134         encPart = new EncAPRepPart(encoding);
135     }
136 
authenticate(KrbApReq apReq)137     private void authenticate(KrbApReq apReq)
138         throws KrbException, IOException {
139         if (encPart.ctime.getSeconds() != apReq.getCtime().getSeconds() ||
140             encPart.cusec != apReq.getCtime().getMicroSeconds())
141             throw new KrbApErrException(Krb5.KRB_AP_ERR_MUT_FAIL);
142     }
143 
144 
145     /**
146      * Returns the optional subkey stored in
147      * this message. Returns null if none is stored.
148      */
getSubKey()149     public EncryptionKey getSubKey() {
150         // XXX Can encPart be null
151         return encPart.getSubKey();
152 
153     }
154 
155     /**
156      * Returns the optional sequence number stored in the
157      * this message. Returns null if none is stored.
158      */
getSeqNumber()159     public Integer getSeqNumber() {
160         // XXX Can encPart be null
161         return encPart.getSeqNumber();
162     }
163 
164     /**
165      * Returns the ASN.1 encoding that should be sent to the peer.
166      */
getMessage()167     public byte[] getMessage() {
168         return obuf;
169     }
170 
createMessage( EncryptionKey key, KerberosTime ctime, int cusec, EncryptionKey subKey, SeqNumber seqNumber)171     private void createMessage(
172                                EncryptionKey key,
173                                KerberosTime ctime,
174                                int cusec,
175                                EncryptionKey subKey,
176                                SeqNumber seqNumber)
177         throws Asn1Exception, IOException,
178                KdcErrException, KrbCryptoException {
179 
180         Integer seqno = null;
181 
182         if (seqNumber != null)
183             seqno = seqNumber.current();
184 
185         encPart = new EncAPRepPart(ctime,
186                                    cusec,
187                                    subKey,
188                                    seqno);
189 
190         byte[] encPartEncoding = encPart.asn1Encode();
191 
192         EncryptedData encEncPart = new EncryptedData(key, encPartEncoding,
193             KeyUsage.KU_ENC_AP_REP_PART);
194 
195         apRepMessg = new APRep(encEncPart);
196     }
197 
198 }
199