xref: /aosp_15_r20/external/cronet/net/data/gencerts/openssl_conf.py (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker#!/usr/bin/env python
2*6777b538SAndroid Build Coastguard Worker# Copyright 2015 The Chromium Authors
3*6777b538SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be
4*6777b538SAndroid Build Coastguard Worker# found in the LICENSE file.
5*6777b538SAndroid Build Coastguard Worker
6*6777b538SAndroid Build Coastguard Worker"""This file contains helpers for representing, manipulating, and writing
7*6777b538SAndroid Build Coastguard WorkerOpenSSL configuration files [1]
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard WorkerConfiguration files are simply a collection of name=value "properties", which
10*6777b538SAndroid Build Coastguard Workerare grouped into "sections".
11*6777b538SAndroid Build Coastguard Worker
12*6777b538SAndroid Build Coastguard Worker[1] https://www.openssl.org/docs/manmaster/apps/config.html
13*6777b538SAndroid Build Coastguard Worker"""
14*6777b538SAndroid Build Coastguard Worker
15*6777b538SAndroid Build Coastguard Workerclass Property(object):
16*6777b538SAndroid Build Coastguard Worker  """Represents a key/value pair in OpenSSL .cnf files.
17*6777b538SAndroid Build Coastguard Worker
18*6777b538SAndroid Build Coastguard Worker  Names and values are not quoted in any way, so callers need to pass the text
19*6777b538SAndroid Build Coastguard Worker  exactly as it should be written to the file (leading and trailing whitespace
20*6777b538SAndroid Build Coastguard Worker  doesn't matter).
21*6777b538SAndroid Build Coastguard Worker
22*6777b538SAndroid Build Coastguard Worker  For instance:
23*6777b538SAndroid Build Coastguard Worker      baseConstraints = critical, CA:false
24*6777b538SAndroid Build Coastguard Worker
25*6777b538SAndroid Build Coastguard Worker  Could be represented by a Property where:
26*6777b538SAndroid Build Coastguard Worker    name = 'baseConstraints'
27*6777b538SAndroid Build Coastguard Worker    value = 'critical, CA:false'
28*6777b538SAndroid Build Coastguard Worker  """
29*6777b538SAndroid Build Coastguard Worker  def __init__(self, name, value):
30*6777b538SAndroid Build Coastguard Worker    self.name = name
31*6777b538SAndroid Build Coastguard Worker    self.value = value
32*6777b538SAndroid Build Coastguard Worker
33*6777b538SAndroid Build Coastguard Worker
34*6777b538SAndroid Build Coastguard Worker  def write_to(self, out):
35*6777b538SAndroid Build Coastguard Worker    """Outputs this property to .cnf file."""
36*6777b538SAndroid Build Coastguard Worker    out.write('%s = %s\n' % (self.name, self.value))
37*6777b538SAndroid Build Coastguard Worker
38*6777b538SAndroid Build Coastguard Worker
39*6777b538SAndroid Build Coastguard Workerclass Section(object):
40*6777b538SAndroid Build Coastguard Worker  """Represents a section in OpenSSL. For instance:
41*6777b538SAndroid Build Coastguard Worker      [CA_root]
42*6777b538SAndroid Build Coastguard Worker      preserve = true
43*6777b538SAndroid Build Coastguard Worker
44*6777b538SAndroid Build Coastguard Worker  Could be represented by a Section where:
45*6777b538SAndroid Build Coastguard Worker    name = 'CA_root'
46*6777b538SAndroid Build Coastguard Worker    properties = [Property('preserve', 'true')]
47*6777b538SAndroid Build Coastguard Worker  """
48*6777b538SAndroid Build Coastguard Worker  def __init__(self, name):
49*6777b538SAndroid Build Coastguard Worker    self.name = name
50*6777b538SAndroid Build Coastguard Worker    self.properties = []
51*6777b538SAndroid Build Coastguard Worker
52*6777b538SAndroid Build Coastguard Worker
53*6777b538SAndroid Build Coastguard Worker  def ensure_property_name_not_duplicated(self, name):
54*6777b538SAndroid Build Coastguard Worker    """Raises an exception of there is more than 1 property named |name|."""
55*6777b538SAndroid Build Coastguard Worker    count = 0
56*6777b538SAndroid Build Coastguard Worker    for prop in self.properties:
57*6777b538SAndroid Build Coastguard Worker      if prop.name == name:
58*6777b538SAndroid Build Coastguard Worker        count += 1
59*6777b538SAndroid Build Coastguard Worker    if count > 1:
60*6777b538SAndroid Build Coastguard Worker      raise Exception('Duplicate property: %s' % (name))
61*6777b538SAndroid Build Coastguard Worker
62*6777b538SAndroid Build Coastguard Worker
63*6777b538SAndroid Build Coastguard Worker  def set_property(self, name, value):
64*6777b538SAndroid Build Coastguard Worker    """Replaces, adds, or removes a Property from the Section:
65*6777b538SAndroid Build Coastguard Worker
66*6777b538SAndroid Build Coastguard Worker      - If |value| is None, then this is equivalent to calling
67*6777b538SAndroid Build Coastguard Worker        remove_property(name)
68*6777b538SAndroid Build Coastguard Worker      - If there is an existing property matching |name| then its value is
69*6777b538SAndroid Build Coastguard Worker        replaced with |value|
70*6777b538SAndroid Build Coastguard Worker      - If there are no properties matching |name| then a new one is added at
71*6777b538SAndroid Build Coastguard Worker        the end of the section
72*6777b538SAndroid Build Coastguard Worker
73*6777b538SAndroid Build Coastguard Worker    It is expected that there is AT MOST 1 property with the given name. If
74*6777b538SAndroid Build Coastguard Worker    that is not the case then this function will raise an error."""
75*6777b538SAndroid Build Coastguard Worker
76*6777b538SAndroid Build Coastguard Worker    if value is None:
77*6777b538SAndroid Build Coastguard Worker      self.remove_property(name)
78*6777b538SAndroid Build Coastguard Worker      return
79*6777b538SAndroid Build Coastguard Worker
80*6777b538SAndroid Build Coastguard Worker    self.ensure_property_name_not_duplicated(name)
81*6777b538SAndroid Build Coastguard Worker
82*6777b538SAndroid Build Coastguard Worker    for prop in self.properties:
83*6777b538SAndroid Build Coastguard Worker      if prop.name == name:
84*6777b538SAndroid Build Coastguard Worker        prop.value = value
85*6777b538SAndroid Build Coastguard Worker        return
86*6777b538SAndroid Build Coastguard Worker
87*6777b538SAndroid Build Coastguard Worker    self.add_property(name, value)
88*6777b538SAndroid Build Coastguard Worker
89*6777b538SAndroid Build Coastguard Worker
90*6777b538SAndroid Build Coastguard Worker  def add_property(self, name, value):
91*6777b538SAndroid Build Coastguard Worker    """Adds a property (allows duplicates)"""
92*6777b538SAndroid Build Coastguard Worker    self.properties.append(Property(name, value))
93*6777b538SAndroid Build Coastguard Worker
94*6777b538SAndroid Build Coastguard Worker
95*6777b538SAndroid Build Coastguard Worker  def remove_property(self, name):
96*6777b538SAndroid Build Coastguard Worker    """Removes the property with the indicated name, if it exists.
97*6777b538SAndroid Build Coastguard Worker
98*6777b538SAndroid Build Coastguard Worker    It is expected that there is AT MOST 1 property with the given name. If
99*6777b538SAndroid Build Coastguard Worker    that is not the case then this function will raise an error."""
100*6777b538SAndroid Build Coastguard Worker    self.ensure_property_name_not_duplicated(name)
101*6777b538SAndroid Build Coastguard Worker
102*6777b538SAndroid Build Coastguard Worker    for i in range(len(self.properties)):
103*6777b538SAndroid Build Coastguard Worker      if self.properties[i].name == name:
104*6777b538SAndroid Build Coastguard Worker        self.properties.pop(i)
105*6777b538SAndroid Build Coastguard Worker        return
106*6777b538SAndroid Build Coastguard Worker
107*6777b538SAndroid Build Coastguard Worker
108*6777b538SAndroid Build Coastguard Worker  def clear_properties(self):
109*6777b538SAndroid Build Coastguard Worker    """Removes all configured properties."""
110*6777b538SAndroid Build Coastguard Worker    self.properties = []
111*6777b538SAndroid Build Coastguard Worker
112*6777b538SAndroid Build Coastguard Worker
113*6777b538SAndroid Build Coastguard Worker  def write_to(self, out):
114*6777b538SAndroid Build Coastguard Worker    """Outputs the section in the format used by .cnf files"""
115*6777b538SAndroid Build Coastguard Worker    out.write('[%s]\n' % (self.name))
116*6777b538SAndroid Build Coastguard Worker    for prop in self.properties:
117*6777b538SAndroid Build Coastguard Worker      prop.write_to(out)
118*6777b538SAndroid Build Coastguard Worker    out.write('\n')
119*6777b538SAndroid Build Coastguard Worker
120*6777b538SAndroid Build Coastguard Worker
121*6777b538SAndroid Build Coastguard Workerclass Config(object):
122*6777b538SAndroid Build Coastguard Worker  """Represents a .cnf (configuration) file in OpenSSL"""
123*6777b538SAndroid Build Coastguard Worker  def __init__(self):
124*6777b538SAndroid Build Coastguard Worker    self.sections = []
125*6777b538SAndroid Build Coastguard Worker
126*6777b538SAndroid Build Coastguard Worker
127*6777b538SAndroid Build Coastguard Worker  def get_section(self, name):
128*6777b538SAndroid Build Coastguard Worker    """Gets or creates a section with the given name."""
129*6777b538SAndroid Build Coastguard Worker    for section in self.sections:
130*6777b538SAndroid Build Coastguard Worker      if section.name == name:
131*6777b538SAndroid Build Coastguard Worker        return section
132*6777b538SAndroid Build Coastguard Worker    new_section = Section(name)
133*6777b538SAndroid Build Coastguard Worker    self.sections.append(new_section)
134*6777b538SAndroid Build Coastguard Worker    return new_section
135*6777b538SAndroid Build Coastguard Worker
136*6777b538SAndroid Build Coastguard Worker
137*6777b538SAndroid Build Coastguard Worker  def write_to_file(self, path):
138*6777b538SAndroid Build Coastguard Worker    """Outputs the Config to a .cnf files."""
139*6777b538SAndroid Build Coastguard Worker    with open(path, 'w') as out:
140*6777b538SAndroid Build Coastguard Worker      for section in self.sections:
141*6777b538SAndroid Build Coastguard Worker        section.write_to(out)
142