/**
 * Copyright (c) 2016, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net.wifi.hotspot2;

import android.net.wifi.hotspot2.omadm.PpsMoParser;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import android.util.Pair;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Utility class for building PasspointConfiguration from an installation file.
 */
public final class ConfigParser {
    private static final String TAG = "ConfigParser";

    // Header names.
    private static final String CONTENT_TYPE = "Content-Type";
    private static final String CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding";

    // MIME types.
    private static final String TYPE_MULTIPART_MIXED = "multipart/mixed";
    private static final String TYPE_WIFI_CONFIG = "application/x-wifi-config";
    private static final String TYPE_PASSPOINT_PROFILE = "application/x-passpoint-profile";
    private static final String TYPE_CA_CERT = "application/x-x509-ca-cert";
    private static final String TYPE_PKCS12 = "application/x-pkcs12";

    private static final String ENCODING_BASE64 = "base64";
    private static final String BOUNDARY = "boundary=";

    /**
     * Class represent a MIME (Multipurpose Internet Mail Extension) part.
     */
    private static class MimePart {
        /**
         * Content type of the part.
         */
        public String type = null;

        /**
         * Decoded data.
         */
        public byte[] data = null;

        /**
         * Flag indicating if this is the last part (ending with --{boundary}--).
         */
        public boolean isLast = false;
    }

    /**
     * Class represent the MIME (Multipurpose Internet Mail Extension) header.
     */
    private static class MimeHeader {
        /**
         * Content type.
         */
        public String contentType = null;

        /**
         * Boundary string (optional), only applies for the outter MIME header.
         */
        public String boundary = null;

        /**
         * Encoding type.
         */
        public String encodingType = null;
    }

    /**
     * @hide
     */
    public ConfigParser() {}

    /**
     * Parse the Hotspot 2.0 Release 1 configuration data into a {@link PasspointConfiguration}
     * object.  The configuration data is a base64 encoded MIME multipart data.  Below is
     * the format of the decoded message:
     *
     * Content-Type: multipart/mixed; boundary={boundary}
     * Content-Transfer-Encoding: base64
     * [Skip uninterested headers]
     *
     * --{boundary}
     * Content-Type: application/x-passpoint-profile
     * Content-Transfer-Encoding: base64
     *
     * [base64 encoded Passpoint profile data]
     * --{boundary}
     * Content-Type: application/x-x509-ca-cert
     * Content-Transfer-Encoding: base64
     *
     * [base64 encoded X509 CA certificate data]
     * --{boundary}
     * Content-Type: application/x-pkcs12
     * Content-Transfer-Encoding: base64
     *
     * [base64 encoded PKCS#12 ASN.1 structure containing client certificate chain]
     * --{boundary}
     *
     * @param mimeType MIME type of the encoded data.
     * @param data A base64 encoded MIME multipart message containing the Passpoint profile
     *             (required), CA (Certificate Authority) certificate (optional), and client
     *             certificate chain (optional).
     * @return {@link PasspointConfiguration}
     */
    public static PasspointConfiguration parsePasspointConfig(String mimeType, byte[] data) {
        // Verify MIME type.
        if (!TextUtils.equals(mimeType, TYPE_WIFI_CONFIG)) {
            Log.e(TAG, "Unexpected MIME type: " + mimeType);
            return null;
        }

        try {
            // Decode the data.
            byte[] decodedData = Base64.decode(new String(data, StandardCharsets.ISO_8859_1),
                    Base64.DEFAULT);
            Map<String, byte[]> mimeParts = parseMimeMultipartMessage(new LineNumberReader(
                    new InputStreamReader(new ByteArrayInputStream(decodedData),
                            StandardCharsets.ISO_8859_1)));
            return createPasspointConfig(mimeParts);
        } catch (IOException | IllegalArgumentException e) {
            Log.e(TAG, "Failed to parse installation file: " + e.getMessage());
            return null;
        }
    }

    /**
     * Create a {@link PasspointConfiguration} object from list of MIME (Multipurpose Internet
     * Mail Extension) parts.
     *
     * @param mimeParts Map of content type and content data.
     * @return {@link PasspointConfiguration}
     * @throws IOException
     */
    private static PasspointConfiguration createPasspointConfig(Map<String, byte[]> mimeParts)
            throws IOException {
        byte[] profileData = mimeParts.get(TYPE_PASSPOINT_PROFILE);
        if (profileData == null) {
            throw new IOException("Missing Passpoint Profile");
        }

        PasspointConfiguration config = PpsMoParser.parseMoText(new String(profileData));
        if (config == null) {
            throw new IOException("Failed to parse Passpoint profile");
        }

        // Credential is needed for storing the certificates and private client key.
        if (config.getCredential() == null) {
            throw new IOException("Passpoint profile missing credential");
        }

        // Don't allow the installer to make changes to the update identifier. This is an
        // indicator of an R2 (or newer) network.
        if (config.getUpdateIdentifier() != Integer.MIN_VALUE) {
            config.setUpdateIdentifier(Integer.MIN_VALUE);
        }

        // Parse CA (Certificate Authority) certificate.
        byte[] caCertData = mimeParts.get(TYPE_CA_CERT);
        if (caCertData != null) {
            try {
                config.getCredential().setCaCertificate(parseCACert(caCertData));
            } catch (CertificateException e) {
                throw new IOException("Failed to parse CA Certificate");
            }
        }

        // Parse PKCS12 data for client private key and certificate chain.
        byte[] pkcs12Data = mimeParts.get(TYPE_PKCS12);
        if (pkcs12Data != null) {
            try {
                Pair<PrivateKey, List<X509Certificate>> clientKey = parsePkcs12(pkcs12Data);
                config.getCredential().setClientPrivateKey(clientKey.first);
                config.getCredential().setClientCertificateChain(
                        clientKey.second.toArray(new X509Certificate[clientKey.second.size()]));
            } catch(GeneralSecurityException | IOException e) {
                throw new IOException("Failed to parse PCKS12 string");
            }
        }
        return config;
    }

    /**
     * Parse a MIME (Multipurpose Internet Mail Extension) multipart message from the given
     * input stream.
     *
     * @param in The input stream for reading the message data
     * @return A map of a content type and content data pair
     * @throws IOException
     */
    private static Map<String, byte[]> parseMimeMultipartMessage(LineNumberReader in)
            throws IOException {
        // Parse the outer MIME header.
        MimeHeader header = parseHeaders(in);
        if (!TextUtils.equals(header.contentType, TYPE_MULTIPART_MIXED)) {
            throw new IOException("Invalid content type: " + header.contentType);
        }
        if (TextUtils.isEmpty(header.boundary)) {
            throw new IOException("Missing boundary string");
        }
        if (!TextUtils.equals(header.encodingType, ENCODING_BASE64)) {
            throw new IOException("Unexpected encoding: " + header.encodingType);
        }

        // Read pass the first boundary string.
        for (;;) {
            String line = in.readLine();
            if (line == null) {
                throw new IOException("Unexpected EOF before first boundary @ " +
                        in.getLineNumber());
            }
            if (line.equals("--" + header.boundary)) {
                break;
            }
        }

        // Parse each MIME part.
        Map<String, byte[]> mimeParts = new HashMap<>();
        boolean isLast = false;
        do {
            MimePart mimePart = parseMimePart(in, header.boundary);
            mimeParts.put(mimePart.type, mimePart.data);
            isLast = mimePart.isLast;
        } while(!isLast);
        return mimeParts;
    }

    /**
     * Parse a MIME (Multipurpose Internet Mail Extension) part.  We expect the data to
     * be encoded in base64.
     *
     * @param in Input stream to read the data from
     * @param boundary Boundary string indicate the end of the part
     * @return {@link MimePart}
     * @throws IOException
     */
    private static MimePart parseMimePart(LineNumberReader in, String boundary)
            throws IOException {
        MimeHeader header = parseHeaders(in);
        // Expect encoding type to be base64.
        if (!TextUtils.equals(header.encodingType, ENCODING_BASE64)) {
            throw new IOException("Unexpected encoding type: " + header.encodingType);
        }

        // Check for a valid content type.
        if (!TextUtils.equals(header.contentType, TYPE_PASSPOINT_PROFILE) &&
                !TextUtils.equals(header.contentType, TYPE_CA_CERT) &&
                !TextUtils.equals(header.contentType, TYPE_PKCS12)) {
            throw new IOException("Unexpected content type: " + header.contentType);
        }

        StringBuilder text = new StringBuilder();
        boolean isLast = false;
        String partBoundary = "--" + boundary;
        String endBoundary = partBoundary + "--";
        for (;;) {
            String line = in.readLine();
            if (line == null) {
                throw new IOException("Unexpected EOF file in body @ " + in.getLineNumber());
            }
            // Check for boundary line.
            if (line.startsWith(partBoundary)) {
                if (line.equals(endBoundary)) {
                    isLast = true;
                }
                break;
            }
            text.append(line);
        }

        MimePart part = new MimePart();
        part.type = header.contentType;
        part.data = Base64.decode(text.toString(), Base64.DEFAULT);
        part.isLast = isLast;
        return part;
    }

    /**
     * Parse a MIME (Multipurpose Internet Mail Extension) header from the input stream.
     * @param in Input stream to read from.
     * @return {@link MimeHeader}
     * @throws IOException
     */
    private static MimeHeader parseHeaders(LineNumberReader in)
            throws IOException {
        MimeHeader header = new MimeHeader();

        // Read the header from the input stream.
        Map<String, String> headers = readHeaders(in);

        // Parse each header.
        for (Map.Entry<String, String> entry : headers.entrySet()) {
            switch (entry.getKey()) {
                case CONTENT_TYPE:
                    Pair<String, String> value = parseContentType(entry.getValue());
                    header.contentType = value.first;
                    header.boundary = value.second;
                    break;
                case CONTENT_TRANSFER_ENCODING:
                    header.encodingType = entry.getValue();
                    break;
                default:
                    Log.d(TAG, "Ignore header: " + entry.getKey());
                    break;
            }
        }
        return header;
    }

    /**
     * Parse the Content-Type header value.  The value will contain the content type string and
     * an optional boundary string separated by a ";".  Below are examples of valid Content-Type
     * header value:
     *   multipart/mixed; boundary={boundary}
     *   application/x-passpoint-profile
     *
     * @param contentType The Content-Type value string
     * @return A pair of content type and boundary string
     * @throws IOException
     */
    private static Pair<String, String> parseContentType(String contentType) throws IOException {
        String[] attributes = contentType.split(";");
        String type = null;
        String boundary = null;

        if (attributes.length < 1) {
            throw new IOException("Invalid Content-Type: " + contentType);
        }

        // The type is always the first attribute.
        type = attributes[0].trim();
        // Look for boundary string from the rest of the attributes.
        for (int i = 1; i < attributes.length; i++) {
            String attribute = attributes[i].trim();
            if (!attribute.startsWith(BOUNDARY)) {
                Log.d(TAG, "Ignore Content-Type attribute: " + attributes[i]);
                continue;
            }
            boundary = attribute.substring(BOUNDARY.length());
            // Remove the leading and trailing quote if present.
            if (boundary.length() > 1 && boundary.startsWith("\"") && boundary.endsWith("\"")) {
                boundary = boundary.substring(1, boundary.length()-1);
            }
        }

        return new Pair<String, String>(type, boundary);
    }

    /**
     * Read the headers from the given input stream.  The header section is terminated by
     * an empty line.
     *
     * @param in The input stream to read from
     * @return Map of key-value pairs.
     * @throws IOException
     */
    private static Map<String, String> readHeaders(LineNumberReader in)
            throws IOException {
        Map<String, String> headers = new HashMap<>();
        String line;
        String name = null;
        StringBuilder value = null;
        for (;;) {
            line = in.readLine();
            if (line == null) {
                throw new IOException("Missing line @ " + in.getLineNumber());
            }

            // End of headers section.
            if (line.length() == 0 || line.trim().length() == 0) {
                // Save the previous header line.
                if (name != null) {
                    headers.put(name, value.toString());
                }
                break;
            }

            int nameEnd = line.indexOf(':');
            if (nameEnd < 0) {
                if (value != null) {
                    // Continuation line for the header value.
                    value.append(' ').append(line.trim());
                } else {
                    throw new IOException("Bad header line: '" + line + "' @ " +
                            in.getLineNumber());
                }
            } else {
                // New header line detected, make sure it doesn't start with a whitespace.
                if (Character.isWhitespace(line.charAt(0))) {
                    throw new IOException("Illegal blank prefix in header line '" + line +
                            "' @ " + in.getLineNumber());
                }

                if (name != null) {
                    // Save the previous header line.
                    headers.put(name, value.toString());
                }

                // Setup the current header line.
                name = line.substring(0, nameEnd).trim();
                value = new StringBuilder();
                value.append(line.substring(nameEnd+1).trim());
            }
        }
        return headers;
    }

    /**
     * Parse a CA (Certificate Authority) certificate data and convert it to a
     * X509Certificate object.
     *
     * @param octets Certificate data
     * @return X509Certificate
     * @throws CertificateException
     */
    private static X509Certificate parseCACert(byte[] octets) throws CertificateException {
        CertificateFactory factory = CertificateFactory.getInstance("X.509");
        return (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(octets));
    }

    private static Pair<PrivateKey, List<X509Certificate>> parsePkcs12(byte[] octets)
            throws GeneralSecurityException, IOException {
        KeyStore ks = KeyStore.getInstance("PKCS12");
        ByteArrayInputStream in = new ByteArrayInputStream(octets);
        ks.load(in, new char[0]);
        in.close();

        // Only expects one set of key and certificate chain.
        if (ks.size() != 1) {
            throw new IOException("Unexpected key size: " + ks.size());
        }

        String alias = ks.aliases().nextElement();
        if (alias == null) {
            throw new IOException("No alias found");
        }

        PrivateKey clientKey = (PrivateKey) ks.getKey(alias, null);
        List<X509Certificate> clientCertificateChain = null;
        Certificate[] chain = ks.getCertificateChain(alias);
        if (chain != null) {
            clientCertificateChain = new ArrayList<>();
            for (Certificate certificate : chain) {
                if (!(certificate instanceof X509Certificate)) {
                    throw new IOException("Unexpceted certificate type: " +
                            certificate.getClass());
                }
                clientCertificateChain.add((X509Certificate) certificate);
            }
        }
        return new Pair<PrivateKey, List<X509Certificate>>(clientKey, clientCertificateChain);
    }
}
