1"""STIX 2.1 Cyber Observable Objects.
2
3Embedded observable object types, such as Email MIME Component, which is
4embedded in Email Message objects, inherit from ``_STIXBase21`` instead of
5_Observable and do not have a ``_type`` attribute.
6"""
7
8from collections import OrderedDict
9import itertools
10
11from ..custom import _custom_extension_builder, _custom_observable_builder
12from ..exceptions import AtLeastOnePropertyError, DependentPropertiesError
13from ..properties import (
14    BinaryProperty, BooleanProperty, DictionaryProperty,
15    EmbeddedObjectProperty, EnumProperty, ExtensionsProperty, FloatProperty,
16    HashesProperty, HexProperty, IDProperty, IntegerProperty, ListProperty,
17    ReferenceProperty, StringProperty, TimestampProperty, TypeProperty,
18)
19from .base import _Extension, _Observable, _STIXBase21
20from .common import GranularMarking
21
22
23class Artifact(_Observable):
24    """For more detailed information on this object's properties, see
25    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_rqwyxo6gp7cv>`__.
26    """
27
28    _type = 'artifact'
29    _properties = OrderedDict([
30        ('type', TypeProperty(_type, spec_version='2.1')),
31        ('spec_version', StringProperty(fixed='2.1')),
32        ('id', IDProperty(_type, spec_version='2.1')),
33        ('mime_type', StringProperty()),
34        ('payload_bin', BinaryProperty()),
35        ('url', StringProperty()),
36        ('hashes', HashesProperty(spec_version='2.1')),
37        ('encryption_algorithm', StringProperty()),
38        ('decryption_key', StringProperty()),
39        ('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
40        ('granular_markings', ListProperty(GranularMarking)),
41        ('defanged', BooleanProperty(default=lambda: False)),
42        ('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=_type)),
43    ])
44    _id_contributing_properties = ["hashes", "payload_bin"]
45
46    def _check_object_constraints(self):
47        super(Artifact, self)._check_object_constraints()
48        self._check_mutually_exclusive_properties(['payload_bin', 'url'])
49        self._check_properties_dependency(['hashes'], ['url'])
50
51
52class AutonomousSystem(_Observable):
53    """For more detailed information on this object's properties, see
54    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_bxebwa6l91fb>`__.
55    """
56
57    _type = 'autonomous-system'
58    _properties = OrderedDict([
59        ('type', TypeProperty(_type, spec_version='2.1')),
60        ('spec_version', StringProperty(fixed='2.1')),
61        ('id', IDProperty(_type, spec_version='2.1')),
62        ('number', IntegerProperty(required=True)),
63        ('name', StringProperty()),
64        ('rir', StringProperty()),
65        ('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
66        ('granular_markings', ListProperty(GranularMarking)),
67        ('defanged', BooleanProperty(default=lambda: False)),
68        ('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=_type)),
69    ])
70    _id_contributing_properties = ["number"]
71
72
73class Directory(_Observable):
74    """For more detailed information on this object's properties, see
75    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_vhpkn06q7fvl>`__.
76    """
77
78    _type = 'directory'
79    _properties = OrderedDict([
80        ('type', TypeProperty(_type, spec_version='2.1')),
81        ('spec_version', StringProperty(fixed='2.1')),
82        ('id', IDProperty(_type, spec_version='2.1')),
83        ('path', StringProperty(required=True)),
84        ('path_enc', StringProperty()),
85        # these are not the created/modified timestamps of the object itself
86        ('ctime', TimestampProperty()),
87        ('mtime', TimestampProperty()),
88        ('atime', TimestampProperty()),
89        ('contains_refs', ListProperty(ReferenceProperty(valid_types=['file', 'directory'], spec_version='2.1'))),
90        ('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
91        ('granular_markings', ListProperty(GranularMarking)),
92        ('defanged', BooleanProperty(default=lambda: False)),
93        ('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=_type)),
94    ])
95    _id_contributing_properties = ["path"]
96
97
98class DomainName(_Observable):
99    """For more detailed information on this object's properties, see
100    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_i2zf5h7vnrd9>`__.
101    """
102
103    _type = 'domain-name'
104    _properties = OrderedDict([
105        ('type', TypeProperty(_type, spec_version='2.1')),
106        ('spec_version', StringProperty(fixed='2.1')),
107        ('id', IDProperty(_type, spec_version='2.1')),
108        ('value', StringProperty(required=True)),
109        ('resolves_to_refs', ListProperty(ReferenceProperty(valid_types=['ipv4-addr', 'ipv6-addr', 'domain-name'], spec_version='2.1'))),
110        ('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
111        ('granular_markings', ListProperty(GranularMarking)),
112        ('defanged', BooleanProperty(default=lambda: False)),
113        ('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=_type)),
114    ])
115    _id_contributing_properties = ["value"]
116
117
118class EmailAddress(_Observable):
119    """For more detailed information on this object's properties, see
120    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_am7srelb9c14>`__.
121    """
122
123    _type = 'email-addr'
124    _properties = OrderedDict([
125        ('type', TypeProperty(_type, spec_version='2.1')),
126        ('spec_version', StringProperty(fixed='2.1')),
127        ('id', IDProperty(_type, spec_version='2.1')),
128        ('value', StringProperty(required=True)),
129        ('display_name', StringProperty()),
130        ('belongs_to_ref', ReferenceProperty(valid_types='user-account', spec_version='2.1')),
131        ('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
132        ('granular_markings', ListProperty(GranularMarking)),
133        ('defanged', BooleanProperty(default=lambda: False)),
134        ('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=_type)),
135    ])
136    _id_contributing_properties = ["value"]
137
138
139class EmailMIMEComponent(_STIXBase21):
140    """For more detailed information on this object's properties, see
141    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_kzv52qqc0xw1>`__.
142    """
143
144    _properties = OrderedDict([
145        ('body', StringProperty()),
146        ('body_raw_ref', ReferenceProperty(valid_types=['artifact', 'file'], spec_version="2.1")),
147        ('content_type', StringProperty()),
148        ('content_disposition', StringProperty()),
149    ])
150
151    def _check_object_constraints(self):
152        super(EmailMIMEComponent, self)._check_object_constraints()
153        self._check_at_least_one_property(['body', 'body_raw_ref'])
154
155
156class EmailMessage(_Observable):
157    """For more detailed information on this object's properties, see
158    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_loz634bn09om>`__.
159    """
160
161    _type = 'email-message'
162    _properties = OrderedDict([
163        ('type', TypeProperty(_type, spec_version='2.1')),
164        ('spec_version', StringProperty(fixed='2.1')),
165        ('id', IDProperty(_type, spec_version='2.1')),
166        ('is_multipart', BooleanProperty(required=True)),
167        ('date', TimestampProperty()),
168        ('content_type', StringProperty()),
169        ('from_ref', ReferenceProperty(valid_types='email-addr', spec_version='2.1')),
170        ('sender_ref', ReferenceProperty(valid_types='email-addr', spec_version='2.1')),
171        ('to_refs', ListProperty(ReferenceProperty(valid_types='email-addr', spec_version='2.1'))),
172        ('cc_refs', ListProperty(ReferenceProperty(valid_types='email-addr', spec_version='2.1'))),
173        ('bcc_refs', ListProperty(ReferenceProperty(valid_types='email-addr', spec_version='2.1'))),
174        ('message_id', StringProperty()),
175        ('subject', StringProperty()),
176        ('received_lines', ListProperty(StringProperty)),
177        ('additional_header_fields', DictionaryProperty(spec_version='2.1')),
178        ('body', StringProperty()),
179        ('body_multipart', ListProperty(EmbeddedObjectProperty(type=EmailMIMEComponent))),
180        ('raw_email_ref', ReferenceProperty(valid_types='artifact', spec_version='2.1')),
181        ('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
182        ('granular_markings', ListProperty(GranularMarking)),
183        ('defanged', BooleanProperty(default=lambda: False)),
184        ('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=_type)),
185    ])
186    _id_contributing_properties = ["from_ref", "subject", "body"]
187
188    def _check_object_constraints(self):
189        super(EmailMessage, self)._check_object_constraints()
190        self._check_properties_dependency(['is_multipart'], ['body_multipart'])
191        if self.get('is_multipart') is True and self.get('body'):
192            # 'body' MAY only be used if is_multipart is false.
193            raise DependentPropertiesError(self.__class__, [('is_multipart', 'body')])
194
195
196class ArchiveExt(_Extension):
197    """For more detailed information on this object's properties, see
198    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_mm25z9wuw4tr>`__.
199    """
200
201    _type = 'archive-ext'
202    _properties = OrderedDict([
203        ('contains_refs', ListProperty(ReferenceProperty(valid_types=['file', 'directory'], spec_version="2.1"), required=True)),
204        ('comment', StringProperty()),
205    ])
206
207
208class AlternateDataStream(_STIXBase21):
209    """For more detailed information on this object's properties, see
210    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_nbqgazg6fsma>`__.
211    """
212
213    _properties = OrderedDict([
214        ('name', StringProperty(required=True)),
215        ('hashes', HashesProperty(spec_version='2.1')),
216        ('size', IntegerProperty()),
217    ])
218
219
220class NTFSExt(_Extension):
221    """For more detailed information on this object's properties, see
222    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_tb77nk1g3y6f>`__.
223    """
224
225    _type = 'ntfs-ext'
226    _properties = OrderedDict([
227        ('sid', StringProperty()),
228        ('alternate_data_streams', ListProperty(EmbeddedObjectProperty(type=AlternateDataStream))),
229    ])
230
231
232class PDFExt(_Extension):
233    """For more detailed information on this object's properties, see
234    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_30hzxqrmkg8w>`__.
235    """
236
237    _type = 'pdf-ext'
238    _properties = OrderedDict([
239        ('version', StringProperty()),
240        ('is_optimized', BooleanProperty()),
241        ('document_info_dict', DictionaryProperty(spec_version='2.1')),
242        ('pdfid0', StringProperty()),
243        ('pdfid1', StringProperty()),
244    ])
245
246
247class RasterImageExt(_Extension):
248    """For more detailed information on this object's properties, see
249    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_20mnz0u5ppxr>`__.
250    """
251
252    _type = 'raster-image-ext'
253    _properties = OrderedDict([
254        ('image_height', IntegerProperty()),
255        ('image_width', IntegerProperty()),
256        ('bits_per_pixel', IntegerProperty()),
257        ('exif_tags', DictionaryProperty(spec_version='2.1')),
258    ])
259
260
261class WindowsPEOptionalHeaderType(_STIXBase21):
262    """For more detailed information on this object's properties, see
263    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_wyp5qdc2wugy>`__.
264    """
265
266    _properties = OrderedDict([
267        ('magic_hex', HexProperty()),
268        ('major_linker_version', IntegerProperty()),
269        ('minor_linker_version', IntegerProperty()),
270        ('size_of_code', IntegerProperty(min=0)),
271        ('size_of_initialized_data', IntegerProperty(min=0)),
272        ('size_of_uninitialized_data', IntegerProperty(min=0)),
273        ('address_of_entry_point', IntegerProperty()),
274        ('base_of_code', IntegerProperty()),
275        ('base_of_data', IntegerProperty()),
276        ('image_base', IntegerProperty()),
277        ('section_alignment', IntegerProperty()),
278        ('file_alignment', IntegerProperty()),
279        ('major_os_version', IntegerProperty()),
280        ('minor_os_version', IntegerProperty()),
281        ('major_image_version', IntegerProperty()),
282        ('minor_image_version', IntegerProperty()),
283        ('major_subsystem_version', IntegerProperty()),
284        ('minor_subsystem_version', IntegerProperty()),
285        ('win32_version_value_hex', HexProperty()),
286        ('size_of_image', IntegerProperty(min=0)),
287        ('size_of_headers', IntegerProperty(min=0)),
288        ('checksum_hex', HexProperty()),
289        ('subsystem_hex', HexProperty()),
290        ('dll_characteristics_hex', HexProperty()),
291        ('size_of_stack_reserve', IntegerProperty(min=0)),
292        ('size_of_stack_commit', IntegerProperty(min=0)),
293        ('size_of_heap_reserve', IntegerProperty()),
294        ('size_of_heap_commit', IntegerProperty()),
295        ('loader_flags_hex', HexProperty()),
296        ('number_of_rva_and_sizes', IntegerProperty()),
297        ('hashes', HashesProperty(spec_version='2.1')),
298    ])
299
300    def _check_object_constraints(self):
301        super(WindowsPEOptionalHeaderType, self)._check_object_constraints()
302        self._check_at_least_one_property()
303
304
305class WindowsPESection(_STIXBase21):
306    """For more detailed information on this object's properties, see
307    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_wiqw87xsov3t>`__.
308    """
309
310    _properties = OrderedDict([
311        ('name', StringProperty(required=True)),
312        ('size', IntegerProperty(min=0)),
313        ('entropy', FloatProperty()),
314        ('hashes', HashesProperty(spec_version='2.1')),
315    ])
316
317
318class WindowsPEBinaryExt(_Extension):
319    """For more detailed information on this object's properties, see
320    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_5f9bgdmj91h5>`__.
321    """
322
323    _type = 'windows-pebinary-ext'
324    _properties = OrderedDict([
325        ('pe_type', StringProperty(required=True)),  # open_vocab
326        ('imphash', StringProperty()),
327        ('machine_hex', HexProperty()),
328        ('number_of_sections', IntegerProperty(min=0)),
329        ('time_date_stamp', TimestampProperty(precision='second')),
330        ('pointer_to_symbol_table_hex', HexProperty()),
331        ('number_of_symbols', IntegerProperty(min=0)),
332        ('size_of_optional_header', IntegerProperty(min=0)),
333        ('characteristics_hex', HexProperty()),
334        ('file_header_hashes', HashesProperty(spec_version='2.1')),
335        ('optional_header', EmbeddedObjectProperty(type=WindowsPEOptionalHeaderType)),
336        ('sections', ListProperty(EmbeddedObjectProperty(type=WindowsPESection))),
337    ])
338
339
340class File(_Observable):
341    """For more detailed information on this object's properties, see
342    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_vq03pryd7u32>`__.
343    """
344
345    _type = 'file'
346    _properties = OrderedDict([
347        ('type', TypeProperty(_type, spec_version='2.1')),
348        ('spec_version', StringProperty(fixed='2.1')),
349        ('id', IDProperty(_type, spec_version='2.1')),
350        ('hashes', HashesProperty(spec_version='2.1')),
351        ('size', IntegerProperty(min=0)),
352        ('name', StringProperty()),
353        ('name_enc', StringProperty()),
354        ('magic_number_hex', HexProperty()),
355        ('mime_type', StringProperty()),
356        ('ctime', TimestampProperty()),
357        ('mtime', TimestampProperty()),
358        ('atime', TimestampProperty()),
359        ('parent_directory_ref', ReferenceProperty(valid_types='directory', spec_version='2.1')),
360        ('contains_refs', ListProperty(ReferenceProperty(valid_types=["SCO"], spec_version='2.1'))),
361        ('content_ref', ReferenceProperty(valid_types='artifact', spec_version='2.1')),
362        ('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
363        ('granular_markings', ListProperty(GranularMarking)),
364        ('defanged', BooleanProperty(default=lambda: False)),
365        ('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=_type)),
366    ])
367    _id_contributing_properties = ["hashes", "name", "parent_directory_ref", "extensions"]
368
369    def _check_object_constraints(self):
370        super(File, self)._check_object_constraints()
371        self._check_at_least_one_property(['hashes', 'name'])
372
373
374class IPv4Address(_Observable):
375    """For more detailed information on this object's properties, see
376    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_ta83c412bfsc>`__.
377    """
378
379    _type = 'ipv4-addr'
380    _properties = OrderedDict([
381        ('type', TypeProperty(_type, spec_version='2.1')),
382        ('spec_version', StringProperty(fixed='2.1')),
383        ('id', IDProperty(_type, spec_version='2.1')),
384        ('value', StringProperty(required=True)),
385        ('resolves_to_refs', ListProperty(ReferenceProperty(valid_types='mac-addr', spec_version='2.1'))),
386        ('belongs_to_refs', ListProperty(ReferenceProperty(valid_types='autonomous-system', spec_version='2.1'))),
387        ('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
388        ('granular_markings', ListProperty(GranularMarking)),
389        ('defanged', BooleanProperty(default=lambda: False)),
390        ('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=_type)),
391    ])
392    _id_contributing_properties = ["value"]
393
394
395class IPv6Address(_Observable):
396    """For more detailed information on this object's properties, see
397    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_f76hsv2pvwwq>`__.
398    """
399
400    _type = 'ipv6-addr'
401    _properties = OrderedDict([
402        ('type', TypeProperty(_type, spec_version='2.1')),
403        ('spec_version', StringProperty(fixed='2.1')),
404        ('id', IDProperty(_type, spec_version='2.1')),
405        ('value', StringProperty(required=True)),
406        ('resolves_to_refs', ListProperty(ReferenceProperty(valid_types='mac-addr', spec_version='2.1'))),
407        ('belongs_to_refs', ListProperty(ReferenceProperty(valid_types='autonomous-system', spec_version='2.1'))),
408        ('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
409        ('granular_markings', ListProperty(GranularMarking)),
410        ('defanged', BooleanProperty(default=lambda: False)),
411        ('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=_type)),
412    ])
413    _id_contributing_properties = ["value"]
414
415
416class MACAddress(_Observable):
417    """For more detailed information on this object's properties, see
418    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_6lhrrdef8852>`__.
419    """
420
421    _type = 'mac-addr'
422    _properties = OrderedDict([
423        ('type', TypeProperty(_type, spec_version='2.1')),
424        ('spec_version', StringProperty(fixed='2.1')),
425        ('id', IDProperty(_type, spec_version='2.1')),
426        ('value', StringProperty(required=True)),
427        ('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
428        ('granular_markings', ListProperty(GranularMarking)),
429        ('defanged', BooleanProperty(default=lambda: False)),
430        ('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=_type)),
431    ])
432    _id_contributing_properties = ["value"]
433
434
435class Mutex(_Observable):
436    """For more detailed information on this object's properties, see
437    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_u65ia5eoc7cv>`__.
438    """
439
440    _type = 'mutex'
441    _properties = OrderedDict([
442        ('type', TypeProperty(_type, spec_version='2.1')),
443        ('spec_version', StringProperty(fixed='2.1')),
444        ('id', IDProperty(_type, spec_version='2.1')),
445        ('name', StringProperty(required=True)),
446        ('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
447        ('granular_markings', ListProperty(GranularMarking)),
448        ('defanged', BooleanProperty(default=lambda: False)),
449        ('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=_type)),
450    ])
451    _id_contributing_properties = ["name"]
452
453
454class HTTPRequestExt(_Extension):
455    """For more detailed information on this object's properties, see
456    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_60k6dn28qicj>`__.
457    """
458
459    _type = 'http-request-ext'
460    _properties = OrderedDict([
461        ('request_method', StringProperty(required=True)),
462        ('request_value', StringProperty(required=True)),
463        ('request_version', StringProperty()),
464        ('request_header', DictionaryProperty(spec_version='2.1')),
465        ('message_body_length', IntegerProperty()),
466        ('message_body_data_ref', ReferenceProperty(valid_types='artifact', spec_version="2.1")),
467    ])
468
469
470class ICMPExt(_Extension):
471    # TODO: Add link
472    """For more detailed information on this object's properties, see
473    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_3g6wds21zwzl>`__.
474    """
475
476    _type = 'icmp-ext'
477    _properties = OrderedDict([
478        ('icmp_type_hex', HexProperty(required=True)),
479        ('icmp_code_hex', HexProperty(required=True)),
480    ])
481
482
483class SocketExt(_Extension):
484    """For more detailed information on this object's properties, see
485    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_f54f1hripxsg>`__.
486    """
487
488    _type = 'socket-ext'
489    _properties = OrderedDict([
490        (
491            'address_family', EnumProperty(
492                allowed=[
493                    "AF_UNSPEC",
494                    "AF_INET",
495                    "AF_IPX",
496                    "AF_APPLETALK",
497                    "AF_NETBIOS",
498                    "AF_INET6",
499                    "AF_IRDA",
500                    "AF_BTH",
501                ], required=True,
502            ),
503        ),
504        ('is_blocking', BooleanProperty()),
505        ('is_listening', BooleanProperty()),
506        ('options', DictionaryProperty(spec_version='2.1')),
507        (
508            'socket_type', EnumProperty(allowed=[
509                "SOCK_STREAM",
510                "SOCK_DGRAM",
511                "SOCK_RAW",
512                "SOCK_RDM",
513                "SOCK_SEQPACKET",
514            ]),
515        ),
516        ('socket_descriptor', IntegerProperty(min=0)),
517        ('socket_handle', IntegerProperty()),
518    ])
519
520    def _check_object_constraints(self):
521        super(SocketExt, self)._check_object_constraints()
522
523        options = self.get('options')
524
525        if options is not None:
526            acceptable_prefixes = ["SO_", "ICMP_", "ICMP6_", "IP_", "IPV6_", "MCAST_", "TCP_", "IRLMP_"]
527            for key, val in options.items():
528                if key[:key.find('_') + 1] not in acceptable_prefixes:
529                    raise ValueError("Incorrect options key")
530                if not isinstance(val, int):
531                    raise ValueError("Options value must be an integer")
532
533
534class TCPExt(_Extension):
535    """For more detailed information on this object's properties, see
536    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_2z78x4m8ewcw>`__.
537    """
538
539    _type = 'tcp-ext'
540    _properties = OrderedDict([
541        ('src_flags_hex', HexProperty()),
542        ('dst_flags_hex', HexProperty()),
543    ])
544
545
546class NetworkTraffic(_Observable):
547    """For more detailed information on this object's properties, see
548    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_e5nyr5squmsd>`__.
549    """
550
551    _type = 'network-traffic'
552    _properties = OrderedDict([
553        ('type', TypeProperty(_type, spec_version='2.1')),
554        ('spec_version', StringProperty(fixed='2.1')),
555        ('id', IDProperty(_type, spec_version='2.1')),
556        ('start', TimestampProperty()),
557        ('end', TimestampProperty()),
558        ('is_active', BooleanProperty()),
559        ('src_ref', ReferenceProperty(valid_types=['ipv4-addr', 'ipv6-addr', 'mac-addr', 'domain-name'], spec_version='2.1')),
560        ('dst_ref', ReferenceProperty(valid_types=['ipv4-addr', 'ipv6-addr', 'mac-addr', 'domain-name'], spec_version='2.1')),
561        ('src_port', IntegerProperty(min=0, max=65535)),
562        ('dst_port', IntegerProperty(min=0, max=65535)),
563        ('protocols', ListProperty(StringProperty, required=True)),
564        ('src_byte_count', IntegerProperty(min=0)),
565        ('dst_byte_count', IntegerProperty(min=0)),
566        ('src_packets', IntegerProperty(min=0)),
567        ('dst_packets', IntegerProperty(min=0)),
568        ('ipfix', DictionaryProperty(spec_version='2.1')),
569        ('src_payload_ref', ReferenceProperty(valid_types='artifact', spec_version='2.1')),
570        ('dst_payload_ref', ReferenceProperty(valid_types='artifact', spec_version='2.1')),
571        ('encapsulates_refs', ListProperty(ReferenceProperty(valid_types='network-traffic', spec_version='2.1'))),
572        ('encapsulated_by_ref', ReferenceProperty(valid_types='network-traffic', spec_version='2.1')),
573        ('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
574        ('granular_markings', ListProperty(GranularMarking)),
575        ('defanged', BooleanProperty(default=lambda: False)),
576        ('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=_type)),
577    ])
578    _id_contributing_properties = ["start", "src_ref", "dst_ref", "src_port", "dst_port", "protocols"]
579
580    def _check_object_constraints(self):
581        super(NetworkTraffic, self)._check_object_constraints()
582        self._check_at_least_one_property(['src_ref', 'dst_ref'])
583
584        start = self.get('start')
585        end = self.get('end')
586        is_active = self.get('is_active')
587
588        if end and is_active is not False:
589            msg = "{0.id} 'is_active' must be False if 'end' is present"
590            raise ValueError(msg.format(self))
591
592        if end and is_active is True:
593            msg = "{0.id} if 'is_active' is True, 'end' must not be included"
594            raise ValueError(msg.format(self))
595
596        if start and end and end <= start:
597            msg = "{0.id} 'end' must be greater than 'start'"
598            raise ValueError(msg.format(self))
599
600
601class WindowsProcessExt(_Extension):
602    """For more detailed information on this object's properties, see
603    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_4wfs4ve800kf>`__.
604    """
605
606    _type = 'windows-process-ext'
607    _properties = OrderedDict([
608        ('aslr_enabled', BooleanProperty()),
609        ('dep_enabled', BooleanProperty()),
610        ('priority', StringProperty()),
611        ('owner_sid', StringProperty()),
612        ('window_title', StringProperty()),
613        ('startup_info', DictionaryProperty(spec_version='2.1')),
614        (
615            'integrity_level', EnumProperty(allowed=[
616                "low",
617                "medium",
618                "high",
619                "system",
620            ]),
621        ),
622    ])
623
624
625class WindowsServiceExt(_Extension):
626    """For more detailed information on this object's properties, see
627    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_s2rmoe7djlt>`__.
628    """
629
630    _type = 'windows-service-ext'
631    _properties = OrderedDict([
632        ('service_name', StringProperty()),
633        ('descriptions', ListProperty(StringProperty)),
634        ('display_name', StringProperty()),
635        ('group_name', StringProperty()),
636        (
637            'start_type', EnumProperty(allowed=[
638                "SERVICE_AUTO_START",
639                "SERVICE_BOOT_START",
640                "SERVICE_DEMAND_START",
641                "SERVICE_DISABLED",
642                "SERVICE_SYSTEM_ALERT",
643            ]),
644        ),
645        ('service_dll_refs', ListProperty(ReferenceProperty(valid_types='file', spec_version="2.1"))),
646        (
647            'service_type', EnumProperty(allowed=[
648                "SERVICE_KERNEL_DRIVER",
649                "SERVICE_FILE_SYSTEM_DRIVER",
650                "SERVICE_WIN32_OWN_PROCESS",
651                "SERVICE_WIN32_SHARE_PROCESS",
652            ]),
653        ),
654        (
655            'service_status', EnumProperty(allowed=[
656                "SERVICE_CONTINUE_PENDING",
657                "SERVICE_PAUSE_PENDING",
658                "SERVICE_PAUSED",
659                "SERVICE_RUNNING",
660                "SERVICE_START_PENDING",
661                "SERVICE_STOP_PENDING",
662                "SERVICE_STOPPED",
663            ]),
664        ),
665    ])
666
667
668class Process(_Observable):
669    """For more detailed information on this object's properties, see
670    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_ur7snm473t1d>`__.
671    """
672
673    _type = 'process'
674    _properties = OrderedDict([
675        ('type', TypeProperty(_type, spec_version='2.1')),
676        ('spec_version', StringProperty(fixed='2.1')),
677        ('id', IDProperty(_type, spec_version='2.1')),
678        ('is_hidden', BooleanProperty()),
679        ('pid', IntegerProperty()),
680        # this is not the created timestamps of the object itself
681        ('created_time', TimestampProperty()),
682        ('cwd', StringProperty()),
683        ('command_line', StringProperty()),
684        ('environment_variables', DictionaryProperty(spec_version='2.1')),
685        ('opened_connection_refs', ListProperty(ReferenceProperty(valid_types='network-traffic', spec_version='2.1'))),
686        ('creator_user_ref', ReferenceProperty(valid_types='user-account', spec_version='2.1')),
687        ('image_ref', ReferenceProperty(valid_types='file', spec_version='2.1')),
688        ('parent_ref', ReferenceProperty(valid_types='process', spec_version='2.1')),
689        ('child_refs', ListProperty(ReferenceProperty(valid_types='process', spec_version='2.1'))),
690        ('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
691        ('granular_markings', ListProperty(GranularMarking)),
692        ('defanged', BooleanProperty(default=lambda: False)),
693        ('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=_type)),
694    ])
695    _id_contributing_properties = []
696
697    def _check_object_constraints(self):
698        # no need to check windows-service-ext, since it has a required property
699        super(Process, self)._check_object_constraints()
700        try:
701            self._check_at_least_one_property()
702            if 'windows-process-ext' in self.get('extensions', {}):
703                self.extensions['windows-process-ext']._check_at_least_one_property()
704        except AtLeastOnePropertyError as enclosing_exc:
705            if 'extensions' not in self:
706                raise enclosing_exc
707            else:
708                if 'windows-process-ext' in self.get('extensions', {}):
709                    self.extensions['windows-process-ext']._check_at_least_one_property()
710
711
712class Software(_Observable):
713    """For more detailed information on this object's properties, see
714    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_jru33yeokrmh>`__.
715    """
716
717    _type = 'software'
718    _properties = OrderedDict([
719        ('type', TypeProperty(_type, spec_version='2.1')),
720        ('spec_version', StringProperty(fixed='2.1')),
721        ('id', IDProperty(_type, spec_version='2.1')),
722        ('name', StringProperty(required=True)),
723        ('cpe', StringProperty()),
724        ('swid', StringProperty()),
725        ('languages', ListProperty(StringProperty)),
726        ('vendor', StringProperty()),
727        ('version', StringProperty()),
728        ('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
729        ('granular_markings', ListProperty(GranularMarking)),
730        ('defanged', BooleanProperty(default=lambda: False)),
731        ('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=_type)),
732    ])
733    _id_contributing_properties = ["name", "cpe", "swid", "vendor", "version"]
734
735
736class URL(_Observable):
737    """For more detailed information on this object's properties, see
738    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_6bsklda6vc0c>`__.
739    """
740
741    _type = 'url'
742    _properties = OrderedDict([
743        ('type', TypeProperty(_type, spec_version='2.1')),
744        ('spec_version', StringProperty(fixed='2.1')),
745        ('id', IDProperty(_type, spec_version='2.1')),
746        ('value', StringProperty(required=True)),
747        ('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
748        ('granular_markings', ListProperty(GranularMarking)),
749        ('defanged', BooleanProperty(default=lambda: False)),
750        ('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=_type)),
751    ])
752    _id_contributing_properties = ["value"]
753
754
755class UNIXAccountExt(_Extension):
756    """For more detailed information on this object's properties, see
757    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_z25gmwyz67kl>`__.
758    """
759
760    _type = 'unix-account-ext'
761    _properties = OrderedDict([
762        ('gid', IntegerProperty()),
763        ('groups', ListProperty(StringProperty)),
764        ('home_dir', StringProperty()),
765        ('shell', StringProperty()),
766    ])
767
768
769class UserAccount(_Observable):
770    """For more detailed information on this object's properties, see
771    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_hah33g4ntxnx>`__.
772    """
773
774    _type = 'user-account'
775    _properties = OrderedDict([
776        ('type', TypeProperty(_type, spec_version='2.1')),
777        ('spec_version', StringProperty(fixed='2.1')),
778        ('id', IDProperty(_type, spec_version='2.1')),
779        ('user_id', StringProperty()),
780        ('credential', StringProperty()),
781        ('account_login', StringProperty()),
782        ('account_type', StringProperty()),   # open vocab
783        ('display_name', StringProperty()),
784        ('is_service_account', BooleanProperty()),
785        ('is_privileged', BooleanProperty()),
786        ('can_escalate_privs', BooleanProperty()),
787        ('is_disabled', BooleanProperty()),
788        ('account_created', TimestampProperty()),
789        ('account_expires', TimestampProperty()),
790        ('credential_last_changed', TimestampProperty()),
791        ('account_first_login', TimestampProperty()),
792        ('account_last_login', TimestampProperty()),
793        ('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
794        ('granular_markings', ListProperty(GranularMarking)),
795        ('defanged', BooleanProperty(default=lambda: False)),
796        ('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=_type)),
797    ])
798    _id_contributing_properties = ["account_type", "user_id", "account_login"]
799
800
801class WindowsRegistryValueType(_STIXBase21):
802    """For more detailed information on this object's properties, see
803    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_6jiqabgqp2hp>`__.
804    """
805
806    _type = 'windows-registry-value-type'
807    _properties = OrderedDict([
808        ('name', StringProperty()),
809        ('data', StringProperty()),
810        (
811            'data_type', EnumProperty(allowed=[
812                "REG_NONE",
813                "REG_SZ",
814                "REG_EXPAND_SZ",
815                "REG_BINARY",
816                "REG_DWORD",
817                "REG_DWORD_BIG_ENDIAN",
818                "REG_LINK",
819                "REG_MULTI_SZ",
820                "REG_RESOURCE_LIST",
821                "REG_FULL_RESOURCE_DESCRIPTION",
822                "REG_RESOURCE_REQUIREMENTS_LIST",
823                "REG_QWORD",
824                "REG_INVALID_TYPE",
825            ]),
826        ),
827    ])
828
829
830class WindowsRegistryKey(_Observable):
831    """For more detailed information on this object's properties, see
832    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_bdim4of4dl37>`__.
833    """
834
835    _type = 'windows-registry-key'
836    _properties = OrderedDict([
837        ('type', TypeProperty(_type, spec_version='2.1')),
838        ('spec_version', StringProperty(fixed='2.1')),
839        ('id', IDProperty(_type, spec_version='2.1')),
840        ('key', StringProperty()),
841        ('values', ListProperty(EmbeddedObjectProperty(type=WindowsRegistryValueType))),
842        # this is not the modified timestamps of the object itself
843        ('modified_time', TimestampProperty()),
844        ('creator_user_ref', ReferenceProperty(valid_types='user-account', spec_version='2.1')),
845        ('number_of_subkeys', IntegerProperty()),
846        ('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
847        ('granular_markings', ListProperty(GranularMarking)),
848        ('defanged', BooleanProperty(default=lambda: False)),
849        ('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=_type)),
850    ])
851    _id_contributing_properties = ["key", "values"]
852
853
854class X509V3ExtensionsType(_STIXBase21):
855    """For more detailed information on this object's properties, see
856    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_c1kt4dheb6vz>`__.
857    """
858
859    _type = 'x509-v3-extensions-type'
860    _properties = OrderedDict([
861        ('basic_constraints', StringProperty()),
862        ('name_constraints', StringProperty()),
863        ('policy_constraints', StringProperty()),
864        ('key_usage', StringProperty()),
865        ('extended_key_usage', StringProperty()),
866        ('subject_key_identifier', StringProperty()),
867        ('authority_key_identifier', StringProperty()),
868        ('subject_alternative_name', StringProperty()),
869        ('issuer_alternative_name', StringProperty()),
870        ('subject_directory_attributes', StringProperty()),
871        ('crl_distribution_points', StringProperty()),
872        ('inhibit_any_policy', StringProperty()),
873        ('private_key_usage_period_not_before', TimestampProperty()),
874        ('private_key_usage_period_not_after', TimestampProperty()),
875        ('certificate_policies', StringProperty()),
876        ('policy_mappings', StringProperty()),
877    ])
878
879
880class X509Certificate(_Observable):
881    """For more detailed information on this object's properties, see
882    `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_g3kniyun8ykv>`__.
883    """
884
885    _type = 'x509-certificate'
886    _properties = OrderedDict([
887        ('type', TypeProperty(_type, spec_version='2.1')),
888        ('spec_version', StringProperty(fixed='2.1')),
889        ('id', IDProperty(_type, spec_version='2.1')),
890        ('is_self_signed', BooleanProperty()),
891        ('hashes', HashesProperty(spec_version='2.1')),
892        ('version', StringProperty()),
893        ('serial_number', StringProperty()),
894        ('signature_algorithm', StringProperty()),
895        ('issuer', StringProperty()),
896        ('validity_not_before', TimestampProperty()),
897        ('validity_not_after', TimestampProperty()),
898        ('subject', StringProperty()),
899        ('subject_public_key_algorithm', StringProperty()),
900        ('subject_public_key_modulus', StringProperty()),
901        ('subject_public_key_exponent', IntegerProperty()),
902        ('x509_v3_extensions', EmbeddedObjectProperty(type=X509V3ExtensionsType)),
903        ('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
904        ('granular_markings', ListProperty(GranularMarking)),
905        ('defanged', BooleanProperty(default=lambda: False)),
906        ('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=_type)),
907    ])
908    _id_contributing_properties = ["hashes", "serial_number"]
909
910    def _check_object_constraints(self):
911        super(X509Certificate, self)._check_object_constraints()
912
913        att_list = [
914                'is_self_signed', 'hashes', 'version', 'serial_number',
915                'signature_algorithm', 'issuer', 'validity_not_before',
916                'validity_not_after', 'subject', 'subject_public_key_algorithm',
917                'subject_public_key_modulus', 'subject_public_key_exponent',
918                'x509_v3_extensions',
919        ]
920        self._check_at_least_one_property(att_list)
921
922
923def CustomObservable(type='x-custom-observable', properties=None, id_contrib_props=None):
924    """Custom STIX Cyber Observable Object type decorator.
925
926    Example:
927        >>> from stix2.v21 import CustomObservable
928        >>> from stix2.properties import IntegerProperty, StringProperty
929        >>> @CustomObservable('x-custom-observable', [
930        ...     ('property1', StringProperty(required=True)),
931        ...     ('property2', IntegerProperty()),
932        ... ])
933        ... class MyNewObservableType():
934        ...     pass
935
936    """
937    def wrapper(cls):
938        _properties = list(itertools.chain.from_iterable([
939            [('type', TypeProperty(type, spec_version='2.1'))],
940            [('spec_version', StringProperty(fixed='2.1'))],
941            [('id', IDProperty(type, spec_version='2.1'))],
942            properties,
943            [('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=type))],
944        ]))
945        return _custom_observable_builder(cls, type, _properties, '2.1', _Observable, id_contrib_props)
946    return wrapper
947
948
949def CustomExtension(observable=None, type='x-custom-observable-ext', properties=None):
950    """Decorator for custom extensions to STIX Cyber Observables.
951    """
952    def wrapper(cls):
953        return _custom_extension_builder(cls, observable, type, properties, '2.1', _Extension)
954    return wrapper
955