Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/scapy/volatile.py: 32%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# SPDX-License-Identifier: GPL-2.0-only
2# This file is part of Scapy
3# See https://scapy.net/ for more information
4# Copyright (C) Philippe Biondi <phil@secdev.org>
5# Copyright (C) Michael Farrell <micolous+git@gmail.com>
6# Copyright (C) Gauthier Sebaux
8"""
9Fields that hold random numbers.
10"""
12import copy
13import random
14import time
15import math
16import re
17import uuid
18import struct
19import string
21from scapy.base_classes import Net
22from scapy.compat import bytes_encode, chb, plain_str
23from scapy.utils import corrupt_bits, corrupt_bytes
25from typing import (
26 List,
27 TypeVar,
28 Generic,
29 Set,
30 Union,
31 Any,
32 Dict,
33 Optional,
34 Tuple,
35 cast,
36)
38####################
39# Random numbers #
40####################
43class RandomEnumeration:
44 """iterate through a sequence in random order.
45 When all the values have been drawn, if forever=1, the drawing is done again. # noqa: E501
46 If renewkeys=0, the draw will be in the same order, guaranteeing that the same # noqa: E501
47 number will be drawn in not less than the number of integers of the sequence""" # noqa: E501
49 def __init__(self, inf, sup, seed=None, forever=1, renewkeys=0):
50 # type: (int, int, Optional[int], int, int) -> None
51 self.forever = forever
52 self.renewkeys = renewkeys
53 self.inf = inf
54 self.rnd = random.Random(seed)
55 self.sbox_size = 256
57 self.top = sup - inf + 1
59 n = 0
60 while (1 << n) < self.top:
61 n += 1
62 self.n = n
64 self.fs = min(3, (n + 1) // 2)
65 self.fsmask = 2**self.fs - 1
66 self.rounds = max(self.n, 3)
67 self.turns = 0
68 self.i = 0
70 def __iter__(self):
71 # type: () -> RandomEnumeration
72 return self
74 def next(self):
75 # type: () -> int
76 while True:
77 if self.turns == 0 or (self.i == 0 and self.renewkeys):
78 self.cnt_key = self.rnd.randint(0, 2**self.n - 1)
79 self.sbox = [self.rnd.randint(0, self.fsmask)
80 for _ in range(self.sbox_size)]
81 self.turns += 1
82 while self.i < 2**self.n:
83 ct = self.i ^ self.cnt_key
84 self.i += 1
85 for _ in range(self.rounds): # Unbalanced Feistel Network
86 lsb = ct & self.fsmask
87 ct >>= self.fs
88 lsb ^= self.sbox[ct % self.sbox_size]
89 ct |= lsb << (self.n - self.fs)
91 if ct < self.top:
92 return self.inf + ct
93 self.i = 0
94 if not self.forever:
95 raise StopIteration
96 __next__ = next
99_T = TypeVar('_T')
102class VolatileValue(Generic[_T]):
103 def __repr__(self):
104 # type: () -> str
105 return "<%s>" % self.__class__.__name__
107 def _command_args(self):
108 # type: () -> str
109 return ''
111 def command(self, json=False):
112 # type: (bool) -> Union[Dict[str, str], str]
113 if json:
114 return {"type": self.__class__.__name__, "value": self._command_args()}
115 else:
116 return "%s(%s)" % (self.__class__.__name__, self._command_args())
118 def __eq__(self, other):
119 # type: (Any) -> bool
120 x = self._fix()
121 y = other._fix() if isinstance(other, VolatileValue) else other
122 if not isinstance(x, type(y)):
123 return False
124 return bool(x == y)
126 def __ne__(self, other):
127 # type: (Any) -> bool
128 # Python 2.7 compat
129 return not self == other
131 __hash__ = None # type: ignore
133 def __getattr__(self, attr):
134 # type: (str) -> Any
135 if attr in ["__setstate__", "__getstate__"]:
136 raise AttributeError(attr)
137 return getattr(self._fix(), attr)
139 def __str__(self):
140 # type: () -> str
141 return str(self._fix())
143 def __bytes__(self):
144 # type: () -> bytes
145 return bytes_encode(self._fix())
147 def __len__(self):
148 # type: () -> int
149 # Does not work for some types (int?)
150 return len(self._fix()) # type: ignore
152 def copy(self):
153 # type: () -> Any
154 return copy.copy(self)
156 def _fix(self):
157 # type: () -> _T
158 return cast(_T, None)
161class RandField(VolatileValue[_T], Generic[_T]):
162 pass
165_I = TypeVar("_I", int, float)
168class _RandNumeral(RandField[_I]):
169 """Implements integer management in RandField"""
171 def __int__(self):
172 # type: () -> int
173 return int(self._fix())
175 def __index__(self):
176 # type: () -> int
177 return int(self)
179 def __nonzero__(self):
180 # type: () -> bool
181 return bool(self._fix())
182 __bool__ = __nonzero__
184 def __add__(self, other):
185 # type: (_I) -> _I
186 return self._fix() + other
188 def __radd__(self, other):
189 # type: (_I) -> _I
190 return other + self._fix()
192 def __sub__(self, other):
193 # type: (_I) -> _I
194 return self._fix() - other
196 def __rsub__(self, other):
197 # type: (_I) -> _I
198 return other - self._fix()
200 def __mul__(self, other):
201 # type: (_I) -> _I
202 return self._fix() * other
204 def __rmul__(self, other):
205 # type: (_I) -> _I
206 return other * self._fix()
208 def __floordiv__(self, other):
209 # type: (_I) -> float
210 return self._fix() / other
211 __div__ = __floordiv__
213 def __lt__(self, other):
214 # type: (_I) -> bool
215 return self._fix() < other
217 def __le__(self, other):
218 # type: (_I) -> bool
219 return self._fix() <= other
221 def __ge__(self, other):
222 # type: (_I) -> bool
223 return self._fix() >= other
225 def __gt__(self, other):
226 # type: (_I) -> bool
227 return self._fix() > other
230class RandNum(_RandNumeral[int]):
231 """Instances evaluate to random integers in selected range"""
232 min = 0
233 max = 0
235 def __init__(self, min, max):
236 # type: (int, int) -> None
237 self.min = min
238 self.max = max
240 def _command_args(self):
241 # type: () -> str
242 if self.__class__.__name__ == 'RandNum':
243 return "min=%r, max=%r" % (self.min, self.max)
244 return super(RandNum, self)._command_args()
246 def _fix(self):
247 # type: () -> int
248 return random.randrange(self.min, self.max + 1)
250 def __lshift__(self, other):
251 # type: (int) -> int
252 return self._fix() << other
254 def __rshift__(self, other):
255 # type: (int) -> int
256 return self._fix() >> other
258 def __and__(self, other):
259 # type: (int) -> int
260 return self._fix() & other
262 def __rand__(self, other):
263 # type: (int) -> int
264 return other & self._fix()
266 def __or__(self, other):
267 # type: (int) -> int
268 return self._fix() | other
270 def __ror__(self, other):
271 # type: (int) -> int
272 return other | self._fix()
275class RandFloat(_RandNumeral[float]):
276 def __init__(self, min, max):
277 # type: (int, int) -> None
278 self.min = min
279 self.max = max
281 def _fix(self):
282 # type: () -> float
283 return random.uniform(self.min, self.max)
286class RandBinFloat(RandFloat):
287 def _fix(self):
288 # type: () -> float
289 return cast(
290 float,
291 struct.unpack("!f", bytes(RandBin(4)))[0]
292 )
295class RandNumGamma(RandNum):
296 def __init__(self, alpha, beta):
297 # type: (int, int) -> None
298 self.alpha = alpha
299 self.beta = beta
301 def _command_args(self):
302 # type: () -> str
303 return "alpha=%r, beta=%r" % (self.alpha, self.beta)
305 def _fix(self):
306 # type: () -> int
307 return int(round(random.gammavariate(self.alpha, self.beta)))
310class RandNumGauss(RandNum):
311 def __init__(self, mu, sigma):
312 # type: (int, int) -> None
313 self.mu = mu
314 self.sigma = sigma
316 def _command_args(self):
317 # type: () -> str
318 return "mu=%r, sigma=%r" % (self.mu, self.sigma)
320 def _fix(self):
321 # type: () -> int
322 return int(round(random.gauss(self.mu, self.sigma)))
325class RandNumExpo(RandNum):
326 def __init__(self, lambd, base=0):
327 # type: (float, int) -> None
328 self.lambd = lambd
329 self.base = base
331 def _command_args(self):
332 # type: () -> str
333 ret = "lambd=%r" % self.lambd
334 if self.base != 0:
335 ret += ", base=%r" % self.base
336 return ret
338 def _fix(self):
339 # type: () -> int
340 return self.base + int(round(random.expovariate(self.lambd)))
343class RandEnum(RandNum):
344 """Instances evaluate to integer sampling without replacement from the given interval""" # noqa: E501
346 def __init__(self, min, max, seed=None):
347 # type: (int, int, Optional[int]) -> None
348 self._seed = seed
349 self.seq = RandomEnumeration(min, max, seed)
350 super(RandEnum, self).__init__(min, max)
352 def _command_args(self):
353 # type: () -> str
354 ret = "min=%r, max=%r" % (self.min, self.max)
355 if self._seed:
356 ret += ", seed=%r" % self._seed
357 return ret
359 def _fix(self):
360 # type: () -> int
361 return next(self.seq)
364class RandByte(RandNum):
365 def __init__(self):
366 # type: () -> None
367 RandNum.__init__(self, 0, 2**8 - 1)
370class RandSByte(RandNum):
371 def __init__(self):
372 # type: () -> None
373 RandNum.__init__(self, -2**7, 2**7 - 1)
376class RandShort(RandNum):
377 def __init__(self):
378 # type: () -> None
379 RandNum.__init__(self, 0, 2**16 - 1)
382class RandSShort(RandNum):
383 def __init__(self):
384 # type: () -> None
385 RandNum.__init__(self, -2**15, 2**15 - 1)
388class RandInt(RandNum):
389 def __init__(self):
390 # type: () -> None
391 RandNum.__init__(self, 0, 2**32 - 1)
394class RandSInt(RandNum):
395 def __init__(self):
396 # type: () -> None
397 RandNum.__init__(self, -2**31, 2**31 - 1)
400class RandLong(RandNum):
401 def __init__(self):
402 # type: () -> None
403 RandNum.__init__(self, 0, 2**64 - 1)
406class RandSLong(RandNum):
407 def __init__(self):
408 # type: () -> None
409 RandNum.__init__(self, -2**63, 2**63 - 1)
412class RandEnumByte(RandEnum):
413 def __init__(self):
414 # type: () -> None
415 RandEnum.__init__(self, 0, 2**8 - 1)
418class RandEnumSByte(RandEnum):
419 def __init__(self):
420 # type: () -> None
421 RandEnum.__init__(self, -2**7, 2**7 - 1)
424class RandEnumShort(RandEnum):
425 def __init__(self):
426 # type: () -> None
427 RandEnum.__init__(self, 0, 2**16 - 1)
430class RandEnumSShort(RandEnum):
431 def __init__(self):
432 # type: () -> None
433 RandEnum.__init__(self, -2**15, 2**15 - 1)
436class RandEnumInt(RandEnum):
437 def __init__(self):
438 # type: () -> None
439 RandEnum.__init__(self, 0, 2**32 - 1)
442class RandEnumSInt(RandEnum):
443 def __init__(self):
444 # type: () -> None
445 RandEnum.__init__(self, -2**31, 2**31 - 1)
448class RandEnumLong(RandEnum):
449 def __init__(self):
450 # type: () -> None
451 RandEnum.__init__(self, 0, 2**64 - 1)
454class RandEnumSLong(RandEnum):
455 def __init__(self):
456 # type: () -> None
457 RandEnum.__init__(self, -2**63, 2**63 - 1)
460class RandEnumKeys(RandEnum):
461 """Picks a random value from dict keys list. """
463 def __init__(self, enum, seed=None):
464 # type: (Dict[Any, Any], Optional[int]) -> None
465 self.enum = list(enum)
466 RandEnum.__init__(self, 0, len(self.enum) - 1, seed)
468 def _command_args(self):
469 # type: () -> str
470 # Note: only outputs the list of keys, but values are irrelevant anyway
471 ret = "enum=%r" % self.enum
472 if self._seed:
473 ret += ", seed=%r" % self._seed
474 return ret
476 def _fix(self):
477 # type: () -> Any
478 return self.enum[next(self.seq)]
481class RandChoice(RandField[Any]):
482 def __init__(self, *args):
483 # type: (*Any) -> None
484 if not args:
485 raise TypeError("RandChoice needs at least one choice")
486 self._choice = list(args)
488 def _command_args(self):
489 # type: () -> str
490 return ", ".join(self._choice)
492 def _fix(self):
493 # type: () -> Any
494 return random.choice(self._choice)
497_S = TypeVar("_S", bytes, str)
500class _RandString(RandField[_S], Generic[_S]):
501 def __str__(self):
502 # type: () -> str
503 return plain_str(self._fix())
505 def __bytes__(self):
506 # type: () -> bytes
507 return bytes_encode(self._fix())
509 def __mul__(self, n):
510 # type: (int) -> _S
511 return self._fix() * n
514class RandString(_RandString[str]):
515 _DEFAULT_CHARS = (string.ascii_uppercase + string.ascii_lowercase +
516 string.digits)
518 def __init__(self, size=None, chars=_DEFAULT_CHARS):
519 # type: (Optional[Union[int, RandNum]], str) -> None
520 if size is None:
521 size = RandNumExpo(0.01)
522 self.size = size
523 self.chars = chars
525 def _command_args(self):
526 # type: () -> str
527 ret = ""
528 if isinstance(self.size, VolatileValue):
529 if self.size.lambd != 0.01 or self.size.base != 0:
530 ret += "size=%r" % self.size.command()
531 else:
532 ret += "size=%r" % self.size
534 if self.chars != self._DEFAULT_CHARS:
535 ret += ", chars=%r" % self.chars
536 return ret
538 def _fix(self):
539 # type: () -> str
540 s = ""
541 for _ in range(int(self.size)):
542 s += random.choice(self.chars)
543 return s
546class RandBin(_RandString[bytes]):
547 _DEFAULT_CHARS = b"".join(chb(c) for c in range(256))
549 def __init__(self, size=None, chars=_DEFAULT_CHARS):
550 # type: (Optional[Union[int, RandNum]], bytes) -> None
551 if size is None:
552 size = RandNumExpo(0.01)
553 self.size = size
554 self.chars = chars
556 def _command_args(self):
557 # type: () -> str
558 if not isinstance(self.size, VolatileValue):
559 return "size=%r" % self.size
561 if isinstance(self.size, RandNumExpo) and \
562 self.size.lambd == 0.01 and self.size.base == 0:
563 # Default size for RandString, skip
564 return ""
565 return "size=%r" % self.size.command()
567 def _fix(self):
568 # type: () -> bytes
569 s = b""
570 for _ in range(int(self.size)):
571 s += struct.pack("!B", random.choice(self.chars))
572 return s
575class RandTermString(RandBin):
576 def __init__(self, size, term):
577 # type: (Union[int, RandNum], bytes) -> None
578 self.term = bytes_encode(term)
579 super(RandTermString, self).__init__(size=size)
581 def _command_args(self):
582 # type: () -> str
583 return ", ".join((super(RandTermString, self)._command_args(),
584 "term=%r" % self.term))
586 def _fix(self):
587 # type: () -> bytes
588 return RandBin._fix(self) + self.term
591class RandIP(_RandString[str]):
592 _DEFAULT_IPTEMPLATE = "0.0.0.0/0"
594 def __init__(self, iptemplate=_DEFAULT_IPTEMPLATE):
595 # type: (str) -> None
596 super(RandIP, self).__init__()
597 self.ip = Net(iptemplate)
599 def _command_args(self):
600 # type: () -> str
601 rep = "%s/%s" % (self.ip.net, self.ip.mask)
602 if rep == self._DEFAULT_IPTEMPLATE:
603 return ""
604 return "iptemplate=%r" % rep
606 def _fix(self):
607 # type: () -> str
608 return self.ip.choice()
611class RandMAC(_RandString[str]):
612 def __init__(self, _template="*"):
613 # type: (str) -> None
614 super(RandMAC, self).__init__()
615 self._template = _template
616 _template += ":*:*:*:*:*"
617 template = _template.split(":")
618 self.mac = () # type: Tuple[Union[int, RandNum], ...]
619 for i in range(6):
620 v = 0 # type: Union[int, RandNum]
621 if template[i] == "*":
622 v = RandByte()
623 elif "-" in template[i]:
624 x, y = template[i].split("-")
625 v = RandNum(int(x, 16), int(y, 16))
626 else:
627 v = int(template[i], 16)
628 self.mac += (v,)
630 def _command_args(self):
631 # type: () -> str
632 if self._template == "*":
633 return ""
634 return "template=%r" % self._template
636 def _fix(self):
637 # type: () -> str
638 return "%02x:%02x:%02x:%02x:%02x:%02x" % self.mac # type: ignore
641class RandIP6(_RandString[str]):
642 def __init__(self, ip6template="**"):
643 # type: (str) -> None
644 super(RandIP6, self).__init__()
645 self.tmpl = ip6template
646 self.sp = [] # type: List[Union[int, RandNum, str]]
647 for v in self.tmpl.split(":"):
648 if not v or v == "**":
649 self.sp.append(v)
650 continue
651 if "-" in v:
652 a, b = v.split("-")
653 elif v == "*":
654 a = b = ""
655 else:
656 a = b = v
658 if not a:
659 a = "0"
660 if not b:
661 b = "ffff"
662 if a == b:
663 self.sp.append(int(a, 16))
664 else:
665 self.sp.append(RandNum(int(a, 16), int(b, 16)))
666 self.variable = "" in self.sp
667 self.multi = self.sp.count("**")
669 def _command_args(self):
670 # type: () -> str
671 if self.tmpl == "**":
672 return ""
673 return "ip6template=%r" % self.tmpl
675 def _fix(self):
676 # type: () -> str
677 nbm = self.multi
678 ip = [] # type: List[str]
679 for i, n in enumerate(self.sp):
680 if n == "**":
681 nbm -= 1
682 remain = 8 - (len(self.sp) - i - 1) - len(ip) + nbm
683 if "" in self.sp:
684 remain += 1
685 if nbm or self.variable:
686 remain = random.randint(0, remain)
687 for j in range(remain):
688 ip.append("%04x" % random.randint(0, 65535))
689 elif isinstance(n, RandNum):
690 ip.append("%04x" % int(n))
691 elif n == 0:
692 ip.append("0")
693 elif not n:
694 ip.append("")
695 else:
696 ip.append("%04x" % int(n))
697 if len(ip) == 9:
698 ip.remove("")
699 if ip[-1] == "":
700 ip[-1] = "0"
701 return ":".join(ip)
704class RandOID(_RandString[str]):
705 def __init__(self, fmt=None, depth=RandNumExpo(0.1), idnum=RandNumExpo(0.01)): # noqa: E501
706 # type: (Optional[str], RandNumExpo, RandNumExpo) -> None
707 super(RandOID, self).__init__()
708 self.ori_fmt = fmt
709 self.fmt = None # type: Optional[List[Union[str, Tuple[int, ...]]]]
710 if fmt is not None:
711 self.fmt = [
712 tuple(map(int, x.split("-"))) if "-" in x else x
713 for x in fmt.split(".")
714 ]
715 self.depth = depth
716 self.idnum = idnum
718 def _command_args(self):
719 # type: () -> str
720 ret = []
721 if self.fmt:
722 ret.append("fmt=%r" % self.ori_fmt)
724 if not isinstance(self.depth, VolatileValue):
725 ret.append("depth=%r" % self.depth)
726 elif not isinstance(self.depth, RandNumExpo) or \
727 self.depth.lambd != 0.1 or self.depth.base != 0:
728 ret.append("depth=%s" % self.depth.command())
730 if not isinstance(self.idnum, VolatileValue):
731 ret.append("idnum=%r" % self.idnum)
732 elif not isinstance(self.idnum, RandNumExpo) or \
733 self.idnum.lambd != 0.01 or self.idnum.base != 0:
734 ret.append("idnum=%s" % self.idnum.command())
736 return ", ".join(ret)
738 def __repr__(self):
739 # type: () -> str
740 if self.ori_fmt is None:
741 return "<%s>" % self.__class__.__name__
742 else:
743 return "<%s [%s]>" % (self.__class__.__name__, self.ori_fmt)
745 def _fix(self):
746 # type: () -> str
747 if self.fmt is None:
748 return ".".join(str(self.idnum) for _ in range(1 + self.depth))
749 else:
750 oid = []
751 for i in self.fmt:
752 if i == "*":
753 oid.append(str(self.idnum))
754 elif i == "**":
755 oid += [str(self.idnum) for i in range(1 + self.depth)]
756 elif isinstance(i, tuple):
757 oid.append(str(random.randrange(*i)))
758 else:
759 oid.append(i)
760 return ".".join(oid)
763class RandRegExp(RandField[str]):
764 def __init__(self, regexp, lambda_=0.3):
765 # type: (str, float) -> None
766 self._regexp = regexp
767 self._lambda = lambda_
769 def _command_args(self):
770 # type: () -> str
771 ret = "regexp=%r" % self._regexp
772 if self._lambda != 0.3:
773 ret += ", lambda_=%r" % self._lambda
774 return ret
776 special_sets = {
777 "[:alnum:]": "[a-zA-Z0-9]",
778 "[:alpha:]": "[a-zA-Z]",
779 "[:ascii:]": "[\x00-\x7F]",
780 "[:blank:]": "[ \t]",
781 "[:cntrl:]": "[\x00-\x1F\x7F]",
782 "[:digit:]": "[0-9]",
783 "[:graph:]": "[\x21-\x7E]",
784 "[:lower:]": "[a-z]",
785 "[:print:]": "[\x20-\x7E]",
786 "[:punct:]": "[!\"\\#$%&'()*+,\\-./:;<=>?@\\[\\\\\\]^_{|}~]",
787 "[:space:]": "[ \t\r\n\v\f]",
788 "[:upper:]": "[A-Z]",
789 "[:word:]": "[A-Za-z0-9_]",
790 "[:xdigit:]": "[A-Fa-f0-9]",
791 }
793 @staticmethod
794 def choice_expand(s):
795 # type: (str) -> str
796 m = ""
797 invert = s and s[0] == "^"
798 while True:
799 p = s.find("-")
800 if p < 0:
801 break
802 if p == 0 or p == len(s) - 1:
803 m = "-"
804 if p:
805 s = s[:-1]
806 else:
807 s = s[1:]
808 else:
809 c1 = s[p - 1]
810 c2 = s[p + 1]
811 rng = "".join(map(chr, range(ord(c1), ord(c2) + 1)))
812 s = s[:p - 1] + rng + s[p + 1:]
813 res = m + s
814 if invert:
815 res = "".join(chr(x) for x in range(256) if chr(x) not in res)
816 return res
818 @staticmethod
819 def stack_fix(lst, index):
820 # type: (List[Any], List[Any]) -> str
821 r = ""
822 mul = 1
823 for e in lst:
824 if isinstance(e, list):
825 if mul != 1:
826 mul = mul - 1
827 r += RandRegExp.stack_fix(e[1:] * mul, index)
828 # only the last iteration should be kept for back reference
829 f = RandRegExp.stack_fix(e[1:], index)
830 for i, idx in enumerate(index):
831 if e is idx:
832 index[i] = f
833 r += f
834 mul = 1
835 elif isinstance(e, tuple):
836 kind, val = e
837 if kind == "cite":
838 r += index[val - 1]
839 elif kind == "repeat":
840 mul = val
842 elif kind == "choice":
843 if mul == 1:
844 c = random.choice(val)
845 r += RandRegExp.stack_fix(c[1:], index)
846 else:
847 r += RandRegExp.stack_fix([e] * mul, index)
848 mul = 1
849 else:
850 if mul != 1:
851 r += RandRegExp.stack_fix([e] * mul, index)
852 mul = 1
853 else:
854 r += str(e)
855 return r
857 def _fix(self):
858 # type: () -> str
859 stack = [None]
860 index = []
861 # Give up on typing this
862 current = stack # type: Any
863 i = 0
864 regexp = self._regexp
865 for k, v in self.special_sets.items():
866 regexp = regexp.replace(k, v)
867 ln = len(regexp)
868 interp = True
869 while i < ln:
870 c = regexp[i]
871 i += 1
873 if c == '(':
874 current = [current]
875 current[0].append(current)
876 elif c == '|':
877 p = current[0]
878 ch = p[-1]
879 if not isinstance(ch, tuple):
880 ch = ("choice", [current])
881 p[-1] = ch
882 else:
883 ch[1].append(current)
884 current = [p]
885 elif c == ')':
886 ch = current[0][-1]
887 if isinstance(ch, tuple):
888 ch[1].append(current)
889 index.append(current)
890 current = current[0]
891 elif c == '[' or c == '{':
892 current = [current]
893 current[0].append(current)
894 interp = False
895 elif c == ']':
896 current = current[0]
897 choice = RandRegExp.choice_expand("".join(current.pop()[1:]))
898 current.append(RandChoice(*list(choice)))
899 interp = True
900 elif c == '}':
901 current = current[0]
902 num = "".join(current.pop()[1:])
903 e = current.pop()
904 if "," not in num:
905 current.append([current] + [e] * int(num))
906 else:
907 num_min, num_max = num.split(",")
908 if not num_min:
909 num_min = "0"
910 if num_max:
911 n = RandNum(int(num_min), int(num_max))
912 else:
913 n = RandNumExpo(self._lambda, base=int(num_min))
914 current.append(("repeat", n))
915 current.append(e)
916 interp = True
917 elif c == '\\':
918 c = regexp[i]
919 if c == "s":
920 current.append(RandChoice(" ", "\t"))
921 elif c in "0123456789":
922 current.append("cite", ord(c) - 0x30)
923 i += 1
924 elif not interp:
925 current.append(c)
926 elif c == '+':
927 e = current.pop()
928 current.append([current] + [e] * (int(random.expovariate(self._lambda)) + 1)) # noqa: E501
929 elif c == '*':
930 e = current.pop()
931 current.append([current] + [e] * int(random.expovariate(self._lambda))) # noqa: E501
932 elif c == '?':
933 if random.randint(0, 1):
934 current.pop()
935 elif c == '.':
936 current.append(RandChoice(*[chr(x) for x in range(256)]))
937 elif c == '$' or c == '^':
938 pass
939 else:
940 current.append(c)
942 return RandRegExp.stack_fix(stack[1:], index)
944 def __repr__(self):
945 # type: () -> str
946 return "<%s [%r]>" % (self.__class__.__name__, self._regexp)
949class RandSingularity(RandChoice):
950 pass
953class RandSingNum(RandSingularity):
954 @staticmethod
955 def make_power_of_two(end):
956 # type: (int) -> Set[int]
957 sign = 1
958 if end == 0:
959 end = 1
960 if end < 0:
961 end = -end
962 sign = -1
963 end_n = int(math.log(end) / math.log(2)) + 1
964 return {sign * 2**i for i in range(end_n)}
966 def __init__(self, mn, mx):
967 # type: (int, int) -> None
968 self._mn = mn
969 self._mx = mx
970 sing = {0, mn, mx, int((mn + mx) / 2)}
971 sing |= self.make_power_of_two(mn)
972 sing |= self.make_power_of_two(mx)
973 for i in sing.copy():
974 sing.add(i + 1)
975 sing.add(i - 1)
976 for i in sing.copy():
977 if not mn <= i <= mx:
978 sing.remove(i)
979 super(RandSingNum, self).__init__(*sing)
980 self._choice.sort()
982 def _command_args(self):
983 # type: () -> str
984 if self.__class__.__name__ == 'RandSingNum':
985 return "mn=%r, mx=%r" % (self._mn, self._mx)
986 return super(RandSingNum, self)._command_args()
989class RandSingByte(RandSingNum):
990 def __init__(self):
991 # type: () -> None
992 RandSingNum.__init__(self, 0, 2**8 - 1)
995class RandSingSByte(RandSingNum):
996 def __init__(self):
997 # type: () -> None
998 RandSingNum.__init__(self, -2**7, 2**7 - 1)
1001class RandSingShort(RandSingNum):
1002 def __init__(self):
1003 # type: () -> None
1004 RandSingNum.__init__(self, 0, 2**16 - 1)
1007class RandSingSShort(RandSingNum):
1008 def __init__(self):
1009 # type: () -> None
1010 RandSingNum.__init__(self, -2**15, 2**15 - 1)
1013class RandSingInt(RandSingNum):
1014 def __init__(self):
1015 # type: () -> None
1016 RandSingNum.__init__(self, 0, 2**32 - 1)
1019class RandSingSInt(RandSingNum):
1020 def __init__(self):
1021 # type: () -> None
1022 RandSingNum.__init__(self, -2**31, 2**31 - 1)
1025class RandSingLong(RandSingNum):
1026 def __init__(self):
1027 # type: () -> None
1028 RandSingNum.__init__(self, 0, 2**64 - 1)
1031class RandSingSLong(RandSingNum):
1032 def __init__(self):
1033 # type: () -> None
1034 RandSingNum.__init__(self, -2**63, 2**63 - 1)
1037class RandSingString(RandSingularity):
1038 def __init__(self):
1039 # type: () -> None
1040 choices_list = ["",
1041 "%x",
1042 "%%",
1043 "%s",
1044 "%i",
1045 "%n",
1046 "%x%x%x%x%x%x%x%x%x",
1047 "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
1048 "%",
1049 "%%%",
1050 "A" * 4096,
1051 b"\x00" * 4096,
1052 b"\xff" * 4096,
1053 b"\x7f" * 4096,
1054 b"\x80" * 4096,
1055 " " * 4096,
1056 "\\" * 4096,
1057 "(" * 4096,
1058 "../" * 1024,
1059 "/" * 1024,
1060 "${HOME}" * 512,
1061 " or 1=1 --",
1062 "' or 1=1 --",
1063 '" or 1=1 --',
1064 " or 1=1; #",
1065 "' or 1=1; #",
1066 '" or 1=1; #',
1067 ";reboot;",
1068 "$(reboot)",
1069 "`reboot`",
1070 "index.php%00",
1071 b"\x00",
1072 "%00",
1073 "\\",
1074 "../../../../../../../../../../../../../../../../../etc/passwd", # noqa: E501
1075 "%2e%2e%2f" * 20 + "etc/passwd",
1076 "%252e%252e%252f" * 20 + "boot.ini",
1077 "..%c0%af" * 20 + "etc/passwd",
1078 "..%c0%af" * 20 + "boot.ini",
1079 "//etc/passwd",
1080 r"..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\boot.ini", # noqa: E501
1081 "AUX:",
1082 "CLOCK$",
1083 "COM:",
1084 "CON:",
1085 "LPT:",
1086 "LST:",
1087 "NUL:",
1088 "CON:",
1089 r"C:\CON\CON",
1090 r"C:\boot.ini",
1091 r"\\myserver\share",
1092 "foo.exe:",
1093 "foo.exe\\", ]
1094 super(RandSingString, self).__init__(*choices_list)
1096 def _command_args(self):
1097 # type: () -> str
1098 return ""
1100 def __str__(self):
1101 # type: () -> str
1102 return str(self._fix())
1104 def __bytes__(self):
1105 # type: () -> bytes
1106 return bytes_encode(self._fix())
1109class RandPool(RandField[VolatileValue[Any]]):
1110 def __init__(self, *args):
1111 # type: (*Tuple[VolatileValue[Any], int]) -> None
1112 """Each parameter is a volatile object or a couple (volatile object, weight)""" # noqa: E501
1113 self._args = args
1114 pool = [] # type: List[VolatileValue[Any]]
1115 for p in args:
1116 w = 1
1117 if isinstance(p, tuple):
1118 p, w = p # type: ignore
1119 pool += [cast(VolatileValue[Any], p)] * w
1120 self._pool = pool
1122 def _command_args(self):
1123 # type: () -> str
1124 ret = []
1125 for p in self._args:
1126 if isinstance(p, tuple):
1127 ret.append("(%s, %r)" % (p[0].command(), p[1]))
1128 else:
1129 ret.append(p.command())
1130 return ", ".join(ret)
1132 def _fix(self):
1133 # type: () -> Any
1134 r = random.choice(self._pool)
1135 return r._fix()
1138class RandUUID(RandField[uuid.UUID]):
1139 """Generates a random UUID.
1141 By default, this generates a RFC 4122 version 4 UUID (totally random).
1143 See Python's ``uuid`` module documentation for more information.
1145 Args:
1146 template (optional): A template to build the UUID from. Not valid with
1147 any other option.
1148 node (optional): A 48-bit Host ID. Only valid for version 1 (where it
1149 is optional).
1150 clock_seq (optional): An integer of up to 14-bits for the sequence
1151 number. Only valid for version 1 (where it is
1152 optional).
1153 namespace: A namespace identifier, which is also a UUID. Required for
1154 versions 3 and 5, must be omitted otherwise.
1155 name: string, required for versions 3 and 5, must be omitted otherwise.
1156 version: Version of UUID to use (1, 3, 4 or 5). If omitted, attempts to
1157 guess which version to generate, defaulting to version 4
1158 (totally random).
1160 Raises:
1161 ValueError: on invalid constructor arguments
1162 """
1163 # This was originally scapy.contrib.dce_rpc.RandUUID.
1165 _BASE = "([0-9a-f]{{{0}}}|\\*|[0-9a-f]{{{0}}}:[0-9a-f]{{{0}}})"
1166 _REG = re.compile(
1167 r"^{0}-?{1}-?{1}-?{2}{2}-?{2}{2}{2}{2}{2}{2}$".format(
1168 _BASE.format(8), _BASE.format(4), _BASE.format(2)
1169 ),
1170 re.I
1171 )
1172 VERSIONS = [1, 3, 4, 5]
1174 def __init__(self,
1175 template=None, # type: Optional[Any]
1176 node=None, # type: Optional[int]
1177 clock_seq=None, # type: Optional[int]
1178 namespace=None, # type: Optional[uuid.UUID]
1179 name=None, # type: Optional[str]
1180 version=None, # type: Optional[Any]
1181 ):
1182 # type: (...) -> None
1183 self._template = template
1184 self._ori_version = version
1186 self.uuid_template = None
1187 self.clock_seq = None
1188 self.namespace = None
1189 self.name = None
1190 self.node = None
1191 self.version = None
1193 if template:
1194 if node or clock_seq or namespace or name or version:
1195 raise ValueError("UUID template must be the only parameter, "
1196 "if specified")
1197 tmp = RandUUID._REG.match(template)
1198 if tmp:
1199 template = tmp.groups()
1200 else:
1201 # Invalid template
1202 raise ValueError("UUID template is invalid")
1203 rnd_f = [RandInt] + [RandShort] * 2 + [RandByte] * 8
1204 uuid_template = [] # type: List[Union[int, RandNum]]
1205 for i, t in enumerate(template):
1206 if t == "*":
1207 uuid_template.append(rnd_f[i]())
1208 elif ":" in t:
1209 mini, maxi = t.split(":")
1210 uuid_template.append(
1211 RandNum(int(mini, 16), int(maxi, 16))
1212 )
1213 else:
1214 uuid_template.append(int(t, 16))
1216 self.uuid_template = tuple(uuid_template)
1217 else:
1218 if version:
1219 if version not in RandUUID.VERSIONS:
1220 raise ValueError("version is not supported")
1221 else:
1222 self.version = version
1223 else:
1224 # No version specified, try to guess...
1225 # This could be wrong, and cause an error later!
1226 if node or clock_seq:
1227 self.version = 1
1228 elif namespace and name:
1229 self.version = 5
1230 else:
1231 # Don't know, random!
1232 self.version = 4
1234 # We have a version, now do things...
1235 if self.version == 1:
1236 if namespace or name:
1237 raise ValueError("namespace and name may not be used with "
1238 "version 1")
1239 self.node = node
1240 self.clock_seq = clock_seq
1241 elif self.version in (3, 5):
1242 if node or clock_seq:
1243 raise ValueError("node and clock_seq may not be used with "
1244 "version {}".format(self.version))
1246 self.namespace = namespace
1247 self.name = name
1248 elif self.version == 4:
1249 if namespace or name or node or clock_seq:
1250 raise ValueError("node, clock_seq, node and clock_seq may "
1251 "not be used with version 4. If you "
1252 "did not specify version, you need to "
1253 "specify it explicitly.")
1255 def _command_args(self):
1256 # type: () -> str
1257 ret = []
1258 if self._template:
1259 ret.append("template=%r" % self._template)
1260 if self.node:
1261 ret.append("node=%r" % self.node)
1262 if self.clock_seq:
1263 ret.append("clock_seq=%r" % self.clock_seq)
1264 if self.namespace:
1265 ret.append("namespace=%r" % self.namespace)
1266 if self.name:
1267 ret.append("name=%r" % self.name)
1268 if self._ori_version:
1269 ret.append("version=%r" % self._ori_version)
1270 return ", ".join(ret)
1272 def _fix(self):
1273 # type: () -> uuid.UUID
1274 if self.uuid_template:
1275 return uuid.UUID(("%08x%04x%04x" + ("%02x" * 8))
1276 % self.uuid_template)
1277 elif self.version == 1:
1278 return uuid.uuid1(self.node, self.clock_seq)
1279 elif self.version == 3:
1280 if not self.namespace or not self.name:
1281 raise ValueError("Missing namespace or name")
1282 return uuid.uuid3(self.namespace, self.name)
1283 elif self.version == 4:
1284 return uuid.uuid4()
1285 elif self.version == 5:
1286 if not self.namespace or not self.name:
1287 raise ValueError("Missing namespace or name")
1288 return uuid.uuid5(self.namespace, self.name)
1289 else:
1290 raise ValueError("Unhandled version")
1293# Automatic timestamp
1296class _AutoTime(_RandNumeral[_T], # type: ignore
1297 Generic[_T]):
1298 def __init__(self, base=None, diff=None):
1299 # type: (Optional[int], Optional[float]) -> None
1300 self._base = base
1301 self._ori_diff = diff
1303 if diff is not None:
1304 self.diff = diff
1305 elif base is None:
1306 self.diff = 0.
1307 else:
1308 self.diff = time.time() - base
1310 def _command_args(self):
1311 # type: () -> str
1312 ret = []
1313 if self._base:
1314 ret.append("base=%r" % self._base)
1315 if self._ori_diff:
1316 ret.append("diff=%r" % self._ori_diff)
1317 return ", ".join(ret)
1320class AutoTime(_AutoTime[float]):
1321 def _fix(self):
1322 # type: () -> float
1323 return time.time() - self.diff
1326class IntAutoTime(_AutoTime[int]):
1327 def _fix(self):
1328 # type: () -> int
1329 return int(time.time() - self.diff)
1332class ZuluTime(_AutoTime[str]):
1333 def __init__(self, diff=0):
1334 # type: (int) -> None
1335 super(ZuluTime, self).__init__(diff=diff)
1337 def _fix(self):
1338 # type: () -> str
1339 return time.strftime("%y%m%d%H%M%SZ",
1340 time.gmtime(time.time() + self.diff))
1343class GeneralizedTime(_AutoTime[str]):
1344 def __init__(self, diff=0):
1345 # type: (int) -> None
1346 super(GeneralizedTime, self).__init__(diff=diff)
1348 def _fix(self):
1349 # type: () -> str
1350 return time.strftime("%Y%m%d%H%M%SZ",
1351 time.gmtime(time.time() + self.diff))
1354class DelayedEval(VolatileValue[Any]):
1355 """ Example of usage: DelayedEval("time.time()") """
1357 def __init__(self, expr):
1358 # type: (str) -> None
1359 self.expr = expr
1361 def _command_args(self):
1362 # type: () -> str
1363 return "expr=%r" % self.expr
1365 def _fix(self):
1366 # type: () -> Any
1367 return eval(self.expr)
1370class IncrementalValue(VolatileValue[int]):
1371 def __init__(self, start=0, step=1, restart=-1):
1372 # type: (int, int, int) -> None
1373 self.start = self.val = start
1374 self.step = step
1375 self.restart = restart
1377 def _command_args(self):
1378 # type: () -> str
1379 ret = []
1380 if self.start:
1381 ret.append("start=%r" % self.start)
1382 if self.step != 1:
1383 ret.append("step=%r" % self.step)
1384 if self.restart != -1:
1385 ret.append("restart=%r" % self.restart)
1386 return ", ".join(ret)
1388 def _fix(self):
1389 # type: () -> int
1390 v = self.val
1391 if self.val == self.restart:
1392 self.val = self.start
1393 else:
1394 self.val += self.step
1395 return v
1398class CorruptedBytes(VolatileValue[bytes]):
1399 def __init__(self, s, p=0.01, n=None):
1400 # type: (str, float, Optional[Any]) -> None
1401 self.s = s
1402 self.p = p
1403 self.n = n
1405 def _command_args(self):
1406 # type: () -> str
1407 ret = []
1408 ret.append("s=%r" % self.s)
1409 if self.p != 0.01:
1410 ret.append("p=%r" % self.p)
1411 if self.n:
1412 ret.append("n=%r" % self.n)
1413 return ", ".join(ret)
1415 def _fix(self):
1416 # type: () -> bytes
1417 return corrupt_bytes(self.s, self.p, self.n)
1420class CorruptedBits(CorruptedBytes):
1421 def _fix(self):
1422 # type: () -> bytes
1423 return corrupt_bits(self.s, self.p, self.n)