1/*
2 * Copyright (c) 2000, 2012, 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
32package sun.security.krb5;
33
34import sun.security.krb5.EncryptionKey;
35import sun.security.krb5.internal.*;
36import sun.security.krb5.internal.crypto.*;
37import java.io.IOException;
38
39class KrbSafe extends KrbAppMessage {
40
41    private byte[] obuf;
42    private byte[] userData;
43
44    public KrbSafe(byte[] userData,
45                   Credentials creds,
46                   EncryptionKey subKey,
47                   KerberosTime timestamp,
48                   SeqNumber seqNumber,
49                   HostAddress saddr,
50                   HostAddress raddr
51                   )  throws KrbException, IOException {
52        EncryptionKey reqKey = null;
53        if (subKey != null)
54            reqKey = subKey;
55        else
56            reqKey = creds.key;
57
58        obuf = mk_safe(userData,
59                       reqKey,
60                       timestamp,
61                       seqNumber,
62                       saddr,
63                       raddr
64                       );
65    }
66
67    public KrbSafe(byte[] msg,
68                   Credentials creds,
69                   EncryptionKey subKey,
70                   SeqNumber seqNumber,
71                   HostAddress saddr,
72                   HostAddress raddr,
73                   boolean timestampRequired,
74                   boolean seqNumberRequired
75                   )  throws KrbException, IOException {
76
77        KRBSafe krb_safe = new KRBSafe(msg);
78
79        EncryptionKey reqKey = null;
80        if (subKey != null)
81            reqKey = subKey;
82        else
83            reqKey = creds.key;
84
85        userData = rd_safe(
86                           krb_safe,
87                           reqKey,
88                           seqNumber,
89                           saddr,
90                           raddr,
91                           timestampRequired,
92                           seqNumberRequired,
93                           creds.client
94                           );
95    }
96
97    public byte[] getMessage() {
98        return obuf;
99    }
100
101    public byte[] getData() {
102        return userData;
103    }
104
105    private  byte[] mk_safe(byte[] userData,
106                            EncryptionKey key,
107                            KerberosTime timestamp,
108                            SeqNumber seqNumber,
109                            HostAddress sAddress,
110                            HostAddress rAddress
111                            ) throws Asn1Exception, IOException, KdcErrException,
112                            KrbApErrException, KrbCryptoException {
113
114                                Integer usec = null;
115                                Integer seqno = null;
116
117                                if (timestamp != null)
118                                usec = timestamp.getMicroSeconds();
119
120                                if (seqNumber != null) {
121                                    seqno = seqNumber.current();
122                                    seqNumber.step();
123                                }
124
125                                KRBSafeBody krb_safeBody =
126                                new KRBSafeBody(userData,
127                                                timestamp,
128                                                usec,
129                                                seqno,
130                                                sAddress,
131                                                rAddress
132                                                );
133
134                                byte[] temp = krb_safeBody.asn1Encode();
135                                Checksum cksum = new Checksum(
136                                    Checksum.SAFECKSUMTYPE_DEFAULT,
137                                    temp,
138                                    key,
139                                    KeyUsage.KU_KRB_SAFE_CKSUM
140                                    );
141
142                                KRBSafe krb_safe = new KRBSafe(krb_safeBody, cksum);
143
144                                temp = krb_safe.asn1Encode();
145
146                                return krb_safe.asn1Encode();
147                            }
148
149    private byte[] rd_safe(KRBSafe krb_safe,
150                           EncryptionKey key,
151                           SeqNumber seqNumber,
152                           HostAddress sAddress,
153                           HostAddress rAddress,
154                           boolean timestampRequired,
155                           boolean seqNumberRequired,
156                           PrincipalName cname
157                           ) throws Asn1Exception, KdcErrException,
158                           KrbApErrException, IOException, KrbCryptoException {
159
160                               byte[] temp = krb_safe.safeBody.asn1Encode();
161
162                               if (!krb_safe.cksum.verifyKeyedChecksum(temp, key,
163                                   KeyUsage.KU_KRB_SAFE_CKSUM)) {
164                                       throw new KrbApErrException(
165                                           Krb5.KRB_AP_ERR_MODIFIED);
166                               }
167
168                               check(krb_safe.safeBody.timestamp,
169                                     krb_safe.safeBody.usec,
170                                     krb_safe.safeBody.seqNumber,
171                                     krb_safe.safeBody.sAddress,
172                                     krb_safe.safeBody.rAddress,
173                                     seqNumber,
174                                     sAddress,
175                                     rAddress,
176                                     timestampRequired,
177                                     seqNumberRequired,
178                                     cname
179                                     );
180
181                               return krb_safe.safeBody.userData;
182                           }
183}
184