1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.net.http;
18
19import java.security.cert.X509Certificate;
20
21/**
22 * This class represents a set of one or more SSL errors and the associated SSL
23 * certificate.
24 */
25public class SslError {
26
27    /**
28     * Individual SSL errors (in the order from the least to the most severe):
29     */
30
31    /**
32     * The certificate is not yet valid
33     */
34    public static final int SSL_NOTYETVALID = 0;
35    /**
36     * The certificate has expired
37     */
38    public static final int SSL_EXPIRED = 1;
39    /**
40     * Hostname mismatch
41     */
42    public static final int SSL_IDMISMATCH = 2;
43    /**
44     * The certificate authority is not trusted
45     */
46    public static final int SSL_UNTRUSTED = 3;
47    /**
48     * The date of the certificate is invalid
49     */
50    public static final int SSL_DATE_INVALID = 4;
51    /**
52     * A generic error occurred
53     */
54    public static final int SSL_INVALID = 5;
55
56
57    /**
58     * The number of different SSL errors.
59     * @deprecated This constant is not necessary for using the SslError API and
60     *             can change from release to release.
61     */
62    // Update if you add a new SSL error!!!
63    @Deprecated
64    public static final int SSL_MAX_ERROR = 6;
65
66    /**
67     * The SSL error set bitfield (each individual error is a bit index;
68     * multiple individual errors can be OR-ed)
69     */
70    int mErrors;
71
72    /**
73     * The SSL certificate associated with the error set
74     */
75    final SslCertificate mCertificate;
76
77    /**
78     * The URL associated with the error set.
79     */
80    final String mUrl;
81
82    /**
83     * Creates a new SslError object using the supplied error and certificate.
84     * The URL will be set to the empty string.
85     * @param error The SSL error
86     * @param certificate The associated SSL certificate
87     * @deprecated Use {@link #SslError(int, SslCertificate, String)}
88     */
89    @Deprecated
90    public SslError(int error, SslCertificate certificate) {
91        this(error, certificate, "");
92    }
93
94    /**
95     * Creates a new SslError object using the supplied error and certificate.
96     * The URL will be set to the empty string.
97     * @param error The SSL error
98     * @param certificate The associated SSL certificate
99     * @deprecated Use {@link #SslError(int, X509Certificate, String)}
100     */
101    @Deprecated
102    public SslError(int error, X509Certificate certificate) {
103        this(error, certificate, "");
104    }
105
106    /**
107     * Creates a new SslError object using the supplied error, certificate and
108     * URL.
109     * @param error The SSL error
110     * @param certificate The associated SSL certificate
111     * @param url The associated URL
112     */
113    public SslError(int error, SslCertificate certificate, String url) {
114        assert certificate != null;
115        assert url != null;
116        addError(error);
117        mCertificate = certificate;
118        mUrl = url;
119    }
120
121    /**
122     * Creates a new SslError object using the supplied error, certificate and
123     * URL.
124     * @param error The SSL error
125     * @param certificate The associated SSL certificate
126     * @param url The associated URL
127     */
128    public SslError(int error, X509Certificate certificate, String url) {
129        this(error, new SslCertificate(certificate), url);
130    }
131
132    /**
133     * Creates an SslError object from a chromium error code.
134     * @param error The chromium error code
135     * @param certificate The associated SSL certificate
136     * @param url The associated URL.
137     * @hide  chromium error codes only available inside the framework
138     */
139    public static SslError SslErrorFromChromiumErrorCode(
140            int error, SslCertificate cert, String url) {
141        // The chromium error codes are in:
142        // external/chromium/net/base/net_error_list.h
143        assert (error >= -299 && error <= -200);
144        if (error == -200)
145            return new SslError(SSL_IDMISMATCH, cert, url);
146        if (error == -201)
147            return new SslError(SSL_DATE_INVALID, cert, url);
148        if (error == -202)
149            return new SslError(SSL_UNTRUSTED, cert, url);
150        // Map all other codes to SSL_INVALID.
151        return new SslError(SSL_INVALID, cert, url);
152    }
153
154    /**
155     * Gets the SSL certificate associated with this object.
156     * @return The SSL certificate, non-null.
157     */
158    public SslCertificate getCertificate() {
159        return mCertificate;
160    }
161
162    /**
163     * Gets the URL associated with this object.
164     * @return The URL, non-null.
165     */
166    public String getUrl() {
167        return mUrl;
168    }
169
170    /**
171     * Adds the supplied SSL error to the set.
172     * @param error The SSL error to add
173     * @return True if the error being added is a known SSL error, otherwise
174     *         false.
175     */
176    public boolean addError(int error) {
177        boolean rval = (0 <= error && error < SslError.SSL_MAX_ERROR);
178        if (rval) {
179            mErrors |= (0x1 << error);
180        }
181
182        return rval;
183    }
184
185    /**
186     * Determines whether this object includes the supplied error.
187     * @param error The SSL error to check for
188     * @return True if this object includes the error, otherwise false.
189     */
190    public boolean hasError(int error) {
191        boolean rval = (0 <= error && error < SslError.SSL_MAX_ERROR);
192        if (rval) {
193            rval = ((mErrors & (0x1 << error)) != 0);
194        }
195
196        return rval;
197    }
198
199    /**
200     * Gets the most severe SSL error in this object's set of errors.
201     * Returns -1 if the set is empty.
202     * @return The most severe SSL error, or -1 if the set is empty.
203     */
204    public int getPrimaryError() {
205        if (mErrors != 0) {
206            // go from the most to the least severe errors
207            for (int error = SslError.SSL_MAX_ERROR - 1; error >= 0; --error) {
208                if ((mErrors & (0x1 << error)) != 0) {
209                    return error;
210                }
211            }
212            // mErrors should never be set to an invalid value.
213            assert false;
214        }
215
216        return -1;
217    }
218
219    /**
220     * Returns a string representation of this object.
221     * @return A String representation of this object.
222     */
223    public String toString() {
224        return "primary error: " + getPrimaryError() +
225                " certificate: " + getCertificate() +
226                " on URL: " + getUrl();
227    }
228}
229