AttributeType::_oidReverseMap()   A
last analyzed

Complexity

Conditions 4
Paths 2

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 14
ccs 8
cts 8
cp 1
rs 10
c 0
b 0
f 0
cc 4
nc 2
nop 0
crap 4
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace Sop\X501\ASN1;
6
7
use Sop\ASN1\Element;
8
use Sop\ASN1\Type\Primitive\ObjectIdentifier;
9
use Sop\ASN1\Type\Primitive\PrintableString;
10
use Sop\ASN1\Type\Primitive\UTF8String;
11
use Sop\ASN1\Type\StringType;
12
13
/**
14
 * Implements *AttributeType* ASN.1 type.
15
 *
16
 * @see https://www.itu.int/ITU-T/formal-language/itu-t/x/x501/2012/InformationFramework.html#InformationFramework.AttributeType
17
 */
18
class AttributeType
19
{
20
    // OID's from 2.5.4 arc
21
    const OID_OBJECT_CLASS = '2.5.4.0';
22
    const OID_ALIASED_ENTRY_NAME = '2.5.4.1';
23
    const OID_KNOWLEDGE_INFORMATION = '2.5.4.2';
24
    const OID_COMMON_NAME = '2.5.4.3';
25
    const OID_SURNAME = '2.5.4.4';
26
    const OID_SERIAL_NUMBER = '2.5.4.5';
27
    const OID_COUNTRY_NAME = '2.5.4.6';
28
    const OID_LOCALITY_NAME = '2.5.4.7';
29
    const OID_STATE_OR_PROVINCE_NAME = '2.5.4.8';
30
    const OID_STREET_ADDRESS = '2.5.4.9';
31
    const OID_ORGANIZATION_NAME = '2.5.4.10';
32
    const OID_ORGANIZATIONAL_UNIT_NAME = '2.5.4.11';
33
    const OID_TITLE = '2.5.4.12';
34
    const OID_DESCRIPTION = '2.5.4.13';
35
    const OID_SEARCH_GUIDE = '2.5.4.14';
36
    const OID_BUSINESS_CATEGORY = '2.5.4.15';
37
    const OID_POSTAL_ADDRESS = '2.5.4.16';
38
    const OID_POSTAL_CODE = '2.5.4.17';
39
    const OID_POST_OFFICE_BOX = '2.5.4.18';
40
    const OID_PHYSICAL_DELIVERY_OFFICE_NAME = '2.5.4.19';
41
    const OID_TELEPHONE_NUMBER = '2.5.4.20';
42
    const OID_TELEX_NUMBER = '2.5.4.21';
43
    const OID_TELETEX_TERMINAL_IDENTIFIER = '2.5.4.22';
44
    const OID_FACSIMILE_TELEPHONE_NUMBER = '2.5.4.23';
45
    const OID_X121_ADDRESS = '2.5.4.24';
46
    const OID_INTERNATIONAL_ISDN_NUMBER = '2.5.4.25';
47
    const OID_REGISTERED_ADDRESS = '2.5.4.26';
48
    const OID_DESTINATION_INDICATOR = '2.5.4.27';
49
    const OID_PREFERRED_DELIVERY_METHOD = '2.5.4.28';
50
    const OID_PRESENTATION_ADDRESS = '2.5.4.29';
51
    const OID_SUPPORTED_APPLICATION_CONTEXT = '2.5.4.30';
52
    const OID_MEMBER = '2.5.4.31';
53
    const OID_OWNER = '2.5.4.32';
54
    const OID_ROLE_OCCUPANT = '2.5.4.33';
55
    const OID_SEE_ALSO = '2.5.4.34';
56
    const OID_USER_PASSWORD = '2.5.4.35';
57
    const OID_USER_CERTIFICATE = '2.5.4.36';
58
    const OID_CA_CERTIFICATE = '2.5.4.37';
59
    const OID_AUTHORITY_REVOCATION_LIST = '2.5.4.38';
60
    const OID_CERTIFICATE_REVOCATION_LIST = '2.5.4.39';
61
    const OID_CROSS_CERTIFICATE_PAIR = '2.5.4.40';
62
    const OID_NAME = '2.5.4.41';
63
    const OID_GIVEN_NAME = '2.5.4.42';
64
    const OID_INITIALS = '2.5.4.43';
65
    const OID_GENERATION_QUALIFIER = '2.5.4.44';
66
    const OID_UNIQUE_IDENTIFIER = '2.5.4.45';
67
    const OID_DN_QUALIFIER = '2.5.4.46';
68
    const OID_ENHANCED_SEARCH_GUIDE = '2.5.4.47';
69
    const OID_PROTOCOL_INFORMATION = '2.5.4.48';
70
    const OID_DISTINGUISHED_NAME = '2.5.4.49';
71
    const OID_UNIQUE_MEMBER = '2.5.4.50';
72
    const OID_HOUSE_IDENTIFIER = '2.5.4.51';
73
    const OID_SUPPORTED_ALGORITHMS = '2.5.4.52';
74
    const OID_DELTA_REVOCATION_LIST = '2.5.4.53';
75
    const OID_DMD_NAME = '2.5.4.54';
76
    const OID_CLEARANCE = '2.5.4.55';
77
    const OID_DEFAULT_DIR_QOP = '2.5.4.56';
78
    const OID_ATTRIBUTE_INTEGRITY_INFO = '2.5.4.57';
79
    const OID_ATTRIBUTE_CERTIFICATE = '2.5.4.58';
80
    const OID_ATTRIBUTE_CERTIFICATE_REVOCATION_LIST = '2.5.4.59';
81
    const OID_CONF_KEY_INFO = '2.5.4.60';
82
    const OID_AA_CERTIFICATE = '2.5.4.61';
83
    const OID_ATTRIBUTE_DESCRIPTOR_CERTIFICATE = '2.5.4.62';
84
    const OID_ATTRIBUTE_AUTHORITY_REVOCATION_LIST = '2.5.4.63';
85
    const OID_FAMILY_INFORMATION = '2.5.4.64';
86
    const OID_PSEUDONYM = '2.5.4.65';
87
    const OID_COMMUNICATIONS_SERVICE = '2.5.4.66';
88
    const OID_COMMUNICATIONS_NETWORK = '2.5.4.67';
89
    const OID_CERTIFICATION_PRACTICE_STMT = '2.5.4.68';
90
    const OID_CERTIFICATE_POLICY = '2.5.4.69';
91
    const OID_PKI_PATH = '2.5.4.70';
92
    const OID_PRIV_POLICY = '2.5.4.71';
93
    const OID_ROLE = '2.5.4.72';
94
    const OID_DELEGATION_PATH = '2.5.4.73';
95
    const OID_PROT_PRIV_POLICY = '2.5.4.74';
96
    const OID_XML_PRIVILEGE_INFO = '2.5.4.75';
97
    const OID_XML_PRIV_POLICY = '2.5.4.76';
98
    const OID_UUID_PAIR = '2.5.4.77';
99
    const OID_TAG_OID = '2.5.4.78';
100
    const OID_UII_FORMAT = '2.5.4.79';
101
    const OID_UII_IN_URH = '2.5.4.80';
102
    const OID_CONTENT_URL = '2.5.4.81';
103
    const OID_PERMISSION = '2.5.4.82';
104
    const OID_URI = '2.5.4.83';
105
    const OID_PWD_ATTRIBUTE = '2.5.4.84';
106
    const OID_USER_PWD = '2.5.4.85';
107
    const OID_URN = '2.5.4.86';
108
    const OID_URL = '2.5.4.87';
109
    const OID_UTM_COORDINATES = '2.5.4.88';
110
    const OID_URNC = '2.5.4.89';
111
    const OID_UII = '2.5.4.90';
112
    const OID_EPC = '2.5.4.91';
113
    const OID_TAG_AFI = '2.5.4.92';
114
    const OID_EPC_FORMAT = '2.5.4.93';
115
    const OID_EPC_IN_URN = '2.5.4.94';
116
    const OID_LDAP_URL = '2.5.4.95';
117
    const OID_TAG_LOCATION = '2.5.4.96';
118
    const OID_ORGANIZATION_IDENTIFIER = '2.5.4.97';
119
120
    // Miscellany attribute OID's
121
    const OID_CLEARANCE_X501 = '2.5.1.5.55';
122
123
    /**
124
     * Default ASN.1 string types for attributes.
125
     *
126
     * Attributes not mapped here shall use UTF8String as a default type.
127
     *
128
     * @internal
129
     *
130
     * @var array
131
     */
132
    const MAP_ATTR_TO_STR_TYPE = [
133
        self::OID_DN_QUALIFIER => Element::TYPE_PRINTABLE_STRING,
134
        self::OID_COUNTRY_NAME => Element::TYPE_PRINTABLE_STRING,
135
        self::OID_SERIAL_NUMBER => Element::TYPE_PRINTABLE_STRING,
136
    ];
137
138
    /**
139
     * OID to attribute names mapping.
140
     *
141
     * First name is the primary name. If there's more than one name, others may
142
     * be used as an alias.
143
     *
144
     * Generated using ldap-attribs.py.
145
     *
146
     * @internal
147
     *
148
     * @var array
149
     */
150
    const MAP_OID_TO_NAME = [
151
        '0.9.2342.19200300.100.1.1' => ['uid', 'userid'],
152
        '0.9.2342.19200300.100.1.2' => ['textEncodedORAddress'],
153
        '0.9.2342.19200300.100.1.3' => ['mail', 'rfc822Mailbox'],
154
        '0.9.2342.19200300.100.1.4' => ['info'],
155
        '0.9.2342.19200300.100.1.5' => ['drink', 'favouriteDrink'],
156
        '0.9.2342.19200300.100.1.6' => ['roomNumber'],
157
        '0.9.2342.19200300.100.1.7' => ['photo'],
158
        '0.9.2342.19200300.100.1.8' => ['userClass'],
159
        '0.9.2342.19200300.100.1.9' => ['host'],
160
        '0.9.2342.19200300.100.1.10' => ['manager'],
161
        '0.9.2342.19200300.100.1.11' => ['documentIdentifier'],
162
        '0.9.2342.19200300.100.1.12' => ['documentTitle'],
163
        '0.9.2342.19200300.100.1.13' => ['documentVersion'],
164
        '0.9.2342.19200300.100.1.14' => ['documentAuthor'],
165
        '0.9.2342.19200300.100.1.15' => ['documentLocation'],
166
        '0.9.2342.19200300.100.1.20' => ['homePhone', 'homeTelephoneNumber'],
167
        '0.9.2342.19200300.100.1.21' => ['secretary'],
168
        '0.9.2342.19200300.100.1.22' => ['otherMailbox'],
169
        '0.9.2342.19200300.100.1.25' => ['dc', 'domainComponent'],
170
        '0.9.2342.19200300.100.1.26' => ['aRecord'],
171
        '0.9.2342.19200300.100.1.27' => ['mDRecord'],
172
        '0.9.2342.19200300.100.1.28' => ['mXRecord'],
173
        '0.9.2342.19200300.100.1.29' => ['nSRecord'],
174
        '0.9.2342.19200300.100.1.30' => ['sOARecord'],
175
        '0.9.2342.19200300.100.1.31' => ['cNAMERecord'],
176
        '0.9.2342.19200300.100.1.37' => ['associatedDomain'],
177
        '0.9.2342.19200300.100.1.38' => ['associatedName'],
178
        '0.9.2342.19200300.100.1.39' => ['homePostalAddress'],
179
        '0.9.2342.19200300.100.1.40' => ['personalTitle'],
180
        '0.9.2342.19200300.100.1.41' => ['mobile', 'mobileTelephoneNumber'],
181
        '0.9.2342.19200300.100.1.42' => ['pager', 'pagerTelephoneNumber'],
182
        '0.9.2342.19200300.100.1.43' => ['co', 'friendlyCountryName'],
183
        '0.9.2342.19200300.100.1.44' => ['uniqueIdentifier'],
184
        '0.9.2342.19200300.100.1.45' => ['organizationalStatus'],
185
        '0.9.2342.19200300.100.1.46' => ['janetMailbox'],
186
        '0.9.2342.19200300.100.1.47' => ['mailPreferenceOption'],
187
        '0.9.2342.19200300.100.1.48' => ['buildingName'],
188
        '0.9.2342.19200300.100.1.49' => ['dSAQuality'],
189
        '0.9.2342.19200300.100.1.50' => ['singleLevelQuality'],
190
        '0.9.2342.19200300.100.1.51' => ['subtreeMinimumQuality'],
191
        '0.9.2342.19200300.100.1.52' => ['subtreeMaximumQuality'],
192
        '0.9.2342.19200300.100.1.53' => ['personalSignature'],
193
        '0.9.2342.19200300.100.1.54' => ['dITRedirect'],
194
        '0.9.2342.19200300.100.1.55' => ['audio'],
195
        '0.9.2342.19200300.100.1.56' => ['documentPublisher'],
196
        '0.9.2342.19200300.100.1.60' => ['jpegPhoto'],
197
        '1.2.840.113549.1.9.1' => ['email', 'emailAddress', 'pkcs9email'],
198
        '1.2.840.113556.1.2.102' => ['memberOf'],
199
        '1.3.6.1.1.1.1.0' => ['uidNumber'],
200
        '1.3.6.1.1.1.1.1' => ['gidNumber'],
201
        '1.3.6.1.1.1.1.2' => ['gecos'],
202
        '1.3.6.1.1.1.1.3' => ['homeDirectory'],
203
        '1.3.6.1.1.1.1.4' => ['loginShell'],
204
        '1.3.6.1.1.1.1.5' => ['shadowLastChange'],
205
        '1.3.6.1.1.1.1.6' => ['shadowMin'],
206
        '1.3.6.1.1.1.1.7' => ['shadowMax'],
207
        '1.3.6.1.1.1.1.8' => ['shadowWarning'],
208
        '1.3.6.1.1.1.1.9' => ['shadowInactive'],
209
        '1.3.6.1.1.1.1.10' => ['shadowExpire'],
210
        '1.3.6.1.1.1.1.11' => ['shadowFlag'],
211
        '1.3.6.1.1.1.1.12' => ['memberUid'],
212
        '1.3.6.1.1.1.1.13' => ['memberNisNetgroup'],
213
        '1.3.6.1.1.1.1.14' => ['nisNetgroupTriple'],
214
        '1.3.6.1.1.1.1.15' => ['ipServicePort'],
215
        '1.3.6.1.1.1.1.16' => ['ipServiceProtocol'],
216
        '1.3.6.1.1.1.1.17' => ['ipProtocolNumber'],
217
        '1.3.6.1.1.1.1.18' => ['oncRpcNumber'],
218
        '1.3.6.1.1.1.1.19' => ['ipHostNumber'],
219
        '1.3.6.1.1.1.1.20' => ['ipNetworkNumber'],
220
        '1.3.6.1.1.1.1.21' => ['ipNetmaskNumber'],
221
        '1.3.6.1.1.1.1.22' => ['macAddress'],
222
        '1.3.6.1.1.1.1.23' => ['bootParameter'],
223
        '1.3.6.1.1.1.1.24' => ['bootFile'],
224
        '1.3.6.1.1.1.1.26' => ['nisMapName'],
225
        '1.3.6.1.1.1.1.27' => ['nisMapEntry'],
226
        '1.3.6.1.1.4' => ['vendorName'],
227
        '1.3.6.1.1.5' => ['vendorVersion'],
228
        '1.3.6.1.1.16.4' => ['entryUUID'],
229
        '1.3.6.1.1.20' => ['entryDN'],
230
        '2.5.4.0' => ['objectClass'],
231
        '2.5.4.1' => ['aliasedObjectName', 'aliasedEntryName'],
232
        '2.5.4.2' => ['knowledgeInformation'],
233
        '2.5.4.3' => ['cn', 'commonName'],
234
        '2.5.4.4' => ['sn', 'surname'],
235
        '2.5.4.5' => ['serialNumber'],
236
        '2.5.4.6' => ['c', 'countryName'],
237
        '2.5.4.7' => ['l', 'localityName'],
238
        '2.5.4.8' => ['st', 'stateOrProvinceName'],
239
        '2.5.4.9' => ['street', 'streetAddress'],
240
        '2.5.4.10' => ['o', 'organizationName'],
241
        '2.5.4.11' => ['ou', 'organizationalUnitName'],
242
        '2.5.4.12' => ['title'],
243
        '2.5.4.13' => ['description'],
244
        '2.5.4.14' => ['searchGuide'],
245
        '2.5.4.15' => ['businessCategory'],
246
        '2.5.4.16' => ['postalAddress'],
247
        '2.5.4.17' => ['postalCode'],
248
        '2.5.4.18' => ['postOfficeBox'],
249
        '2.5.4.19' => ['physicalDeliveryOfficeName'],
250
        '2.5.4.20' => ['telephoneNumber'],
251
        '2.5.4.21' => ['telexNumber'],
252
        '2.5.4.22' => ['teletexTerminalIdentifier'],
253
        '2.5.4.23' => ['facsimileTelephoneNumber', 'fax'],
254
        '2.5.4.24' => ['x121Address'],
255
        '2.5.4.25' => ['internationaliSDNNumber'],
256
        '2.5.4.26' => ['registeredAddress'],
257
        '2.5.4.27' => ['destinationIndicator'],
258
        '2.5.4.28' => ['preferredDeliveryMethod'],
259
        '2.5.4.29' => ['presentationAddress'],
260
        '2.5.4.30' => ['supportedApplicationContext'],
261
        '2.5.4.31' => ['member'],
262
        '2.5.4.32' => ['owner'],
263
        '2.5.4.33' => ['roleOccupant'],
264
        '2.5.4.34' => ['seeAlso'],
265
        '2.5.4.35' => ['userPassword'],
266
        '2.5.4.36' => ['userCertificate'],
267
        '2.5.4.37' => ['cACertificate'],
268
        '2.5.4.38' => ['authorityRevocationList'],
269
        '2.5.4.39' => ['certificateRevocationList'],
270
        '2.5.4.40' => ['crossCertificatePair'],
271
        '2.5.4.41' => ['name'],
272
        '2.5.4.42' => ['givenName', 'gn'],
273
        '2.5.4.43' => ['initials'],
274
        '2.5.4.44' => ['generationQualifier'],
275
        '2.5.4.45' => ['x500UniqueIdentifier'],
276
        '2.5.4.46' => ['dnQualifier'],
277
        '2.5.4.47' => ['enhancedSearchGuide'],
278
        '2.5.4.48' => ['protocolInformation'],
279
        '2.5.4.49' => ['distinguishedName'],
280
        '2.5.4.50' => ['uniqueMember'],
281
        '2.5.4.51' => ['houseIdentifier'],
282
        '2.5.4.52' => ['supportedAlgorithms'],
283
        '2.5.4.53' => ['deltaRevocationList'],
284
        '2.5.4.54' => ['dmdName'],
285
        '2.5.4.65' => ['pseudonym'],
286
        '2.5.18.1' => ['createTimestamp'],
287
        '2.5.18.2' => ['modifyTimestamp'],
288
        '2.5.18.3' => ['creatorsName'],
289
        '2.5.18.4' => ['modifiersName'],
290
        '2.5.18.5' => ['administrativeRole'],
291
        '2.5.18.6' => ['subtreeSpecification'],
292
        '2.5.18.9' => ['hasSubordinates'],
293
        '2.5.18.10' => ['subschemaSubentry'],
294
        '2.5.21.1' => ['dITStructureRules'],
295
        '2.5.21.2' => ['dITContentRules'],
296
        '2.5.21.4' => ['matchingRules'],
297
        '2.5.21.5' => ['attributeTypes'],
298
        '2.5.21.6' => ['objectClasses'],
299
        '2.5.21.7' => ['nameForms'],
300
        '2.5.21.8' => ['matchingRuleUse'],
301
        '2.5.21.9' => ['structuralObjectClass'],
302
        '2.16.840.1.113730.3.1.1' => ['carLicense'],
303
        '2.16.840.1.113730.3.1.2' => ['departmentNumber'],
304
        '2.16.840.1.113730.3.1.3' => ['employeeNumber'],
305
        '2.16.840.1.113730.3.1.4' => ['employeeType'],
306
        '2.16.840.1.113730.3.1.34' => ['ref'],
307
        '2.16.840.1.113730.3.1.39' => ['preferredLanguage'],
308
        '2.16.840.1.113730.3.1.40' => ['userSMIMECertificate'],
309
        '2.16.840.1.113730.3.1.216' => ['userPKCS12'],
310
        '2.16.840.1.113730.3.1.241' => ['displayName'],
311
    ];
312
313
    /**
314
     * OID of the attribute.
315
     *
316
     * @var string
317
     */
318
    protected $_oid;
319
320
    /**
321
     * Constructor.
322
     *
323
     * @param string $oid OID in dotted format
324
     */
325 60
    public function __construct(string $oid)
326
    {
327 60
        $this->_oid = $oid;
328 60
    }
329
330
    /**
331
     * Initialize from ASN.1.
332
     *
333
     * @param ObjectIdentifier $oi
334
     *
335
     * @return self
336
     */
337 10
    public static function fromASN1(ObjectIdentifier $oi): self
338
    {
339 10
        return new self($oi->oid());
340
    }
341
342
    /**
343
     * Initialize from attribute name.
344
     *
345
     * @param string $name
346
     *
347
     * @return self
348
     */
349 39
    public static function fromName(string $name): self
350
    {
351 39
        $oid = self::attrNameToOID($name);
352 39
        return new self($oid);
353
    }
354
355
    /**
356
     * Get OID of the attribute.
357
     *
358
     * @return string OID in dotted format
359
     */
360 67
    public function oid(): string
361
    {
362 67
        return $this->_oid;
363
    }
364
365
    /**
366
     * Get name of the attribute.
367
     *
368
     * @return string
369
     */
370 19
    public function typeName(): string
371
    {
372 19
        if (array_key_exists($this->_oid, self::MAP_OID_TO_NAME)) {
373 16
            return self::MAP_OID_TO_NAME[$this->_oid][0];
374
        }
375 3
        return $this->_oid;
376
    }
377
378
    /**
379
     * Generate ASN.1 element.
380
     *
381
     * @return ObjectIdentifier
382
     */
383 11
    public function toASN1(): ObjectIdentifier
384
    {
385 11
        return new ObjectIdentifier($this->_oid);
386
    }
387
388
    /**
389
     * Convert attribute name to OID.
390
     *
391
     * @param string $name Primary attribute name or an alias
392
     *
393
     * @throws \OutOfBoundsException
394
     *
395
     * @return string OID in dotted format
396
     */
397 54
    public static function attrNameToOID(string $name): string
398
    {
399
        // if already in OID form
400 54
        if (preg_match('/^[0-9]+(?:\.[0-9]+)*$/', $name)) {
401 10
            return $name;
402
        }
403 49
        $map = self::_oidReverseMap();
404 49
        $k = strtolower($name);
405 49
        if (!isset($map[$k])) {
406 1
            throw new \OutOfBoundsException("No OID for {$name}.");
407
        }
408 48
        return $map[$k];
409
    }
410
411
    /**
412
     * Get ASN.1 string for given attribute type.
413
     *
414
     * @param string $oid Attribute OID
415
     * @param string $str String
416
     *
417
     * @throws \LogicException
418
     *
419
     * @return StringType
420
     */
421 45
    public static function asn1StringForType(string $oid, string $str): StringType
422
    {
423 45
        if (!array_key_exists($oid, self::MAP_ATTR_TO_STR_TYPE)) {
424 41
            return new UTF8String($str);
425
        }
426 4
        switch (self::MAP_ATTR_TO_STR_TYPE[$oid]) {
427
            case Element::TYPE_PRINTABLE_STRING:
428 4
                return new PrintableString($str);
429
            // @codeCoverageIgnoreStart
430
            default:
431
                // only reachable during development
432
                throw new \LogicException();
433
        }
434
        // @codeCoverageIgnoreEnd
435
    }
436
437
    /**
438
     * Get name to OID lookup map.
439
     *
440
     * @return array
441
     */
442 49
    private static function _oidReverseMap(): array
443
    {
444 49
        static $map;
445 49
        if (!isset($map)) {
446 1
            $map = [];
447
            // for each attribute type
448 1
            foreach (self::MAP_OID_TO_NAME as $oid => $names) {
449
                // for primary name and aliases
450 1
                foreach ($names as $name) {
451 1
                    $map[strtolower($name)] = $oid;
452
                }
453
            }
454
        }
455 49
        return $map;
456
    }
457
}
458