1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5package org.chromium.android_webview;
6
7import org.chromium.net.AndroidPrivateKey;
8
9import java.util.Arrays;
10import java.util.HashMap;
11import java.util.HashSet;
12import java.util.Map;
13import java.util.Set;
14
15/**
16 * Store user's client certificate decision for a host and port pair. Not
17 * thread-safe. All accesses are done on UI thread.
18 */
19public class ClientCertLookupTable {
20
21    /**
22     * A container for the certificate data.
23     */
24    public static class Cert {
25        AndroidPrivateKey mPrivateKey;
26        byte[][] mCertChain;
27        public Cert(AndroidPrivateKey privateKey, byte[][] certChain) {
28            this.mPrivateKey = privateKey;
29            byte[][] newChain = new byte[certChain.length][];
30            for (int i = 0; i < certChain.length; i++) {
31                newChain[i] = Arrays.copyOf(certChain[i], certChain[i].length);
32            }
33            this.mCertChain = newChain;
34        }
35    }
36
37    private final Map<String, Cert> mCerts;
38    private final Set<String> mDenieds;
39
40    // Clear client certificate preferences
41    public void clear() {
42        mCerts.clear();
43        mDenieds.clear();
44    }
45
46    public ClientCertLookupTable() {
47        mCerts = new HashMap<String, Cert>();
48        mDenieds = new HashSet<String>();
49    }
50
51    public void allow(String host, int port, AndroidPrivateKey privateKey, byte[][] chain) {
52        String host_and_port = hostAndPort(host, port);
53        mCerts.put(host_and_port, new Cert(privateKey, chain));
54        mDenieds.remove(host_and_port);
55    }
56
57    public void deny(String host, int port) {
58        String host_and_port = hostAndPort(host, port);
59        mCerts.remove(host_and_port);
60        mDenieds.add(host_and_port);
61    }
62
63    public Cert getCertData(String host, int port) {
64        return mCerts.get(hostAndPort(host, port));
65    }
66
67    public boolean isDenied(String host, int port) {
68        return mDenieds.contains(hostAndPort(host, port));
69    }
70
71    // TODO(sgurun) add a test for this. Not separating host and pair properly will be
72    // a security issue.
73    private static String hostAndPort(String host, int port) {
74        return host + ":" + port;
75    }
76}
77