summaryrefslogtreecommitdiffstats
path: root/proxy/code/src/com/redhat/rhn/common/cert/CertificateFactory.java
blob: 260121516abcba2feb5fe287d433c2e17e01d989 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/**
 * Copyright (c) 2009 Red Hat, Inc.
 *
 * This software is licensed to you under the GNU General Public License,
 * version 2 (GPLv2). There is NO WARRANTY for this software, express or
 * implied, including the implied warranties of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
 * along with this software; if not, see
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
 *
 * Red Hat trademarks are not licensed under GPLv2. No permission is
 * granted to use or replicate Red Hat trademarks that are incorporated
 * in this software or its documentation.
 */
package com.redhat.rhn.common.cert;

import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.net.URL;
import java.util.HashMap;
import java.util.List;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

/**
 * A class for parsing certificates from their XML form. The XML
 * format is identical to the one used by the perl code.
 *
 * Borrowed from project Spacewalk: http://spacewalk.redhat.com
 */
public class CertificateFactory {

    private static final String ELEM_SIGNATURE = "rhn-cert-signature";
    private static final String ELEM_FIELD = "rhn-cert-field";
    private static final String ELEM_CERT = "rhn-cert";

    private static final FieldExtractor[] FIELD_EXTRACTORS = {
            new SimpleExtractor("product", true),
            new SimpleExtractor("owner", true),
            new SimpleExtractor("issued", true),
            new SimpleExtractor("expires", true),
            new SimpleExtractor("slots", true),
            new SimpleExtractor("monitoring-slots", "monitoringSlots"),
            new SimpleExtractor("provisioning-slots", "provisioningSlots"),
            new SimpleExtractor("virtualization_host", "virtualizationSlots"),
            new SimpleExtractor("virtualization_host_platform",
                    "virtualizationPlatformSlots"),
            new SimpleExtractor("nonlinux-slots", "nonlinuxSlots"),
            new SimpleExtractor("satellite-version", "satelliteVersion"),
            new SimpleExtractor("generation"),
            new ChannelFamilyExtractor("channel-families") };

    private static final HashMap FIELD_MAP = new HashMap();

    static {
        for (int i = 0; i < FIELD_EXTRACTORS.length; i++) {
            FIELD_MAP.put(FIELD_EXTRACTORS[i].getFieldName(), FIELD_EXTRACTORS[i]);
        }
    }

    private CertificateFactory() {
    }

    /**
     * Parse the certificate from <code>certString</code>.
     * @param certString valid Satellite Certificate in string form
     * @return the certificate from <code>certString</code>
     * @throws JDOMException XML parsing fails
     * @throws IOException unknown
     */
    public static Certificate read(String certString) throws JDOMException, IOException {
        return readDocument(new SAXBuilder().build(new StringReader(certString)),
                certString);
    }

    /**
     * Parse a certificate from <code>file</code>. The file must contain the
     * certificate in XML form.
     * 
     * @param file the file with the XML certificate
     * @return the certificate from <code>fle</code>
     * @throws JDOMException if parsing the XML fails
     * @throws IOException if reading the file fails
     */
    public static Certificate read(File file) throws JDOMException, IOException {
        return readDocument(new SAXBuilder().build(file), file.getAbsolutePath());
    }

    /**
     * Parse a certificate from the contents of <code>url</code>. The file must
     * contain the certificate in XML form.
     * 
     * @param url the URL at which the XML certificate is located
     * @return the certificate from <code>fle</code>
     * @throws JDOMException if parsing the XML fails
     * @throws IOException if reading the contents of <code>url</code> fails
     */
    public static Certificate read(URL url) throws JDOMException, IOException {
        return readDocument(new SAXBuilder().build(url), url.toExternalForm());
    }

    private static Certificate readDocument(Document doc, String source)
        throws JDOMException {
        Certificate result = new Certificate();
        Element root = doc.getRootElement();
        if (!ELEM_CERT.equals(root.getName())) {
            throw new JDOMException("Expected root element in " + source + 
                    " to be " + ELEM_CERT + " but found " + root.getName());
        }
        Element signature = root.getChild(ELEM_SIGNATURE);
        if (signature == null) {
            throw new JDOMException("Could not find signature element ");
        }
        result.setSignature(signature.getText());
        List children = root.getChildren(ELEM_FIELD);
        for (int i = 0; i < children.size(); i++) {
            Element child = (Element) children.get(i);
            extractField(result, child);
        }
        return result;
    }

    private static void extractField(Certificate result, Element child)
        throws JDOMException {
        String name = child.getAttributeValue("name");
        FieldExtractor e = (FieldExtractor) FIELD_MAP.get(name);
        if (name == null) {
            throw new JDOMException("The field " + name +
                    " is not one of the possible fields for " + ELEM_FIELD);
        }
        e.extract(result, child);
    }
}