AAControlsExtension   A
last analyzed

Complexity

Total Complexity 22

Size/Duplication

Total Lines 214
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 22
lcom 1
cbo 7
dl 0
loc 214
ccs 81
cts 81
cp 1
rs 10
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 2
B _fromDER() 0 41 5
A hasPathLen() 0 4 1
A pathLen() 0 7 2
A hasPermittedAttrs() 0 4 1
A permittedAttrs() 0 7 2
A hasExcludedAttrs() 0 4 1
A excludedAttrs() 0 7 2
A permitUnspecified() 0 4 1
A _valueASN1() 0 25 5
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace X509\Certificate\Extension;
6
7
use ASN1\Element;
8
use ASN1\Type\UnspecifiedType;
9
use ASN1\Type\Constructed\Sequence;
10
use ASN1\Type\Primitive\Boolean;
11
use ASN1\Type\Primitive\Integer;
12
use ASN1\Type\Primitive\ObjectIdentifier;
13
use ASN1\Type\Tagged\ImplicitlyTaggedType;
14
15
/**
16
 * Implements 'AA Controls' certificate extension.
17
 *
18
 * @link https://tools.ietf.org/html/rfc5755#section-7.4
19
 */
20
class AAControlsExtension extends Extension
21
{
22
    /**
23
     * Path length contraint.
24
     *
25
     * @var int|null $_pathLenConstraint
26
     */
27
    protected $_pathLenConstraint;
28
    
29
    /**
30
     * Permitted attributes.
31
     *
32
     * Array of OID's.
33
     *
34
     * @var string[]|null $_permittedAttrs
35
     */
36
    protected $_permittedAttrs;
37
    
38
    /**
39
     * Excluded attributes.
40
     *
41
     * Array of OID's.
42
     *
43
     * @var string[]|null $_excludedAttrs
44
     */
45
    protected $_excludedAttrs;
46
    
47
    /**
48
     * Whether to permit unspecified attributes.
49
     *
50
     * @var bool $_permitUnSpecified
51
     */
52
    protected $_permitUnSpecified;
53
    
54
    /**
55
     * Constructor.
56
     *
57
     * @param bool $critical
58
     * @param int|null $path_len
59
     * @param string[]|null $permitted
60
     * @param string[]|null $excluded
61
     * @param bool $permit_unspecified
62
     */
63 4
    public function __construct(bool $critical, $path_len = null,
64
        array $permitted = null, array $excluded = null, bool $permit_unspecified = true)
65
    {
66 4
        parent::__construct(self::OID_AA_CONTROLS, $critical);
67 4
        $this->_pathLenConstraint = isset($path_len) ? intval($path_len) : null;
68 4
        $this->_permittedAttrs = $permitted;
69 4
        $this->_excludedAttrs = $excluded;
70 4
        $this->_permitUnSpecified = $permit_unspecified;
71 4
    }
72
    
73
    /**
74
     *
75
     * {@inheritdoc}
76
     * @return self
77
     */
78 2
    protected static function _fromDER(string $data, bool $critical): self
79
    {
80 2
        $seq = UnspecifiedType::fromDER($data)->asSequence();
81 2
        $path_len = null;
82 2
        $permitted = null;
83 2
        $excluded = null;
84 2
        $permit_unspecified = true;
85 2
        $idx = 0;
86 2
        if ($seq->has($idx, Element::TYPE_INTEGER)) {
87 1
            $path_len = $seq->at($idx++)
88 1
                ->asInteger()
89 1
                ->intNumber();
90
        }
91 2
        if ($seq->hasTagged(0)) {
92 1
            $attr_seq = $seq->getTagged(0)
93 1
                ->asImplicit(Element::TYPE_SEQUENCE)
94 1
                ->asSequence();
95 1
            $permitted = array_map(
96 1
                function (UnspecifiedType $el) {
97 1
                    return $el->asObjectIdentifier()->oid();
98 1
                }, $attr_seq->elements());
99 1
            $idx++;
100
        }
101 2
        if ($seq->hasTagged(1)) {
102 1
            $attr_seq = $seq->getTagged(1)
103 1
                ->asImplicit(Element::TYPE_SEQUENCE)
104 1
                ->asSequence();
105 1
            $excluded = array_map(
106 1
                function (UnspecifiedType $el) {
107 1
                    return $el->asObjectIdentifier()->oid();
108 1
                }, $attr_seq->elements());
109 1
            $idx++;
110
        }
111 2
        if ($seq->has($idx, Element::TYPE_BOOLEAN)) {
112 1
            $permit_unspecified = $seq->at($idx++)
113 1
                ->asBoolean()
114 1
                ->value();
115
        }
116 2
        return new self($critical, $path_len, $permitted, $excluded,
0 ignored issues
show
Bug introduced by
It seems like $permitted defined by array_map(function (\ASN... $attr_seq->elements()) on line 95 can also be of type array; however, X509\Certificate\Extensi...xtension::__construct() does only seem to accept null|array<integer,string>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Bug introduced by
It seems like $excluded defined by array_map(function (\ASN... $attr_seq->elements()) on line 105 can also be of type array; however, X509\Certificate\Extensi...xtension::__construct() does only seem to accept null|array<integer,string>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
117 2
            $permit_unspecified);
118
    }
119
    
120
    /**
121
     * Check whether path length constraint is present.
122
     *
123
     * @return bool
124
     */
125 2
    public function hasPathLen(): bool
126
    {
127 2
        return isset($this->_pathLenConstraint);
128
    }
129
    
130
    /**
131
     * Get path length constraint.
132
     *
133
     * @throws \LogicException
134
     * @return int
135
     */
136 2
    public function pathLen(): int
137
    {
138 2
        if (!$this->hasPathLen()) {
139 1
            throw new \LogicException("pathLen not set.");
140
        }
141 1
        return $this->_pathLenConstraint;
142
    }
143
    
144
    /**
145
     * Check whether permitted attributes are present.
146
     *
147
     * @return bool
148
     */
149 2
    public function hasPermittedAttrs(): bool
150
    {
151 2
        return isset($this->_permittedAttrs);
152
    }
153
    
154
    /**
155
     * Get OID's of permitted attributes.
156
     *
157
     * @throws \LogicException
158
     * @return string[]
159
     */
160 2
    public function permittedAttrs(): array
161
    {
162 2
        if (!$this->hasPermittedAttrs()) {
163 1
            throw new \LogicException("permittedAttrs not set.");
164
        }
165 1
        return $this->_permittedAttrs;
166
    }
167
    
168
    /**
169
     * Check whether excluded attributes are present.
170
     *
171
     * @return bool
172
     */
173 2
    public function hasExcludedAttrs(): bool
174
    {
175 2
        return isset($this->_excludedAttrs);
176
    }
177
    
178
    /**
179
     * Get OID's of excluded attributes.
180
     *
181
     * @throws \LogicException
182
     * @return string[]
183
     */
184 2
    public function excludedAttrs(): array
185
    {
186 2
        if (!$this->hasExcludedAttrs()) {
187 1
            throw new \LogicException("excludedAttrs not set.");
188
        }
189 1
        return $this->_excludedAttrs;
190
    }
191
    
192
    /**
193
     * Whether to permit attributes that are not explicitly specified in
194
     * neither permitted nor excluded list.
195
     *
196
     * @return bool
197
     */
198 1
    public function permitUnspecified(): bool
199
    {
200 1
        return $this->_permitUnSpecified;
201
    }
202
    
203
    /**
204
     *
205
     * {@inheritdoc}
206
     * @return Sequence
207
     */
208 2
    protected function _valueASN1(): Sequence
209
    {
210 2
        $elements = array();
211 2
        if (isset($this->_pathLenConstraint)) {
212 1
            $elements[] = new Integer($this->_pathLenConstraint);
213
        }
214 2
        if (isset($this->_permittedAttrs)) {
215 1
            $oids = array_map(
216 1
                function ($oid) {
217 1
                    return new ObjectIdentifier($oid);
218 1
                }, $this->_permittedAttrs);
219 1
            $elements[] = new ImplicitlyTaggedType(0, new Sequence(...$oids));
220
        }
221 2
        if (isset($this->_excludedAttrs)) {
222 1
            $oids = array_map(
223 1
                function ($oid) {
224 1
                    return new ObjectIdentifier($oid);
225 1
                }, $this->_excludedAttrs);
226 1
            $elements[] = new ImplicitlyTaggedType(1, new Sequence(...$oids));
227
        }
228 2
        if ($this->_permitUnSpecified !== true) {
229 1
            $elements[] = new Boolean(false);
230
        }
231 2
        return new Sequence(...$elements);
232
    }
233
}
234