ronin-support 0.5.1 → 1.0.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (517) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +11 -0
  3. data/.github/workflows/ruby.yml +27 -0
  4. data/.gitignore +7 -6
  5. data/.mailmap +1 -0
  6. data/.ruby-version +1 -0
  7. data/.yardopts +1 -2
  8. data/ChangeLog.md +533 -137
  9. data/Gemfile +20 -20
  10. data/README.md +137 -61
  11. data/Rakefile +29 -10
  12. data/data/text/homoglyphs/ascii.txt +8 -0
  13. data/data/text/homoglyphs/cyrillic.txt +33 -0
  14. data/data/text/homoglyphs/full_width.txt +81 -0
  15. data/data/text/homoglyphs/greek.txt +21 -0
  16. data/data/text/homoglyphs/latin_numbers.txt +14 -0
  17. data/data/text/homoglyphs/punctuation.txt +7 -0
  18. data/data/text/patterns/network/public_suffix.rb.erb +44 -0
  19. data/examples/ssl_proxy.rb +38 -0
  20. data/examples/tcp_proxy.rb +41 -0
  21. data/gemspec.yml +25 -15
  22. data/lib/ronin/support/archive/core_ext/file.rb +118 -0
  23. data/lib/ronin/{formatting/sql.rb → support/archive/core_ext.rb} +6 -7
  24. data/lib/ronin/support/archive/mixin.rb +213 -0
  25. data/lib/ronin/support/archive/tar/reader.rb +135 -0
  26. data/lib/ronin/support/archive/tar/writer.rb +197 -0
  27. data/lib/ronin/support/archive/tar.rb +155 -0
  28. data/lib/ronin/support/archive/zip/reader/entry.rb +134 -0
  29. data/lib/ronin/support/archive/zip/reader/statistics.rb +76 -0
  30. data/lib/ronin/support/archive/zip/reader.rb +273 -0
  31. data/lib/ronin/support/archive/zip/writer.rb +175 -0
  32. data/lib/ronin/support/archive/zip.rb +105 -0
  33. data/lib/ronin/support/archive.rb +211 -0
  34. data/lib/ronin/support/binary/array.rb +255 -0
  35. data/lib/ronin/support/binary/bit_flip.rb +147 -0
  36. data/lib/ronin/support/binary/buffer.rb +2027 -0
  37. data/lib/ronin/support/binary/byte_slice.rb +324 -0
  38. data/lib/ronin/support/binary/core_ext/array.rb +75 -0
  39. data/lib/ronin/support/binary/core_ext/float.rb +80 -0
  40. data/lib/ronin/support/binary/core_ext/integer.rb +305 -0
  41. data/lib/ronin/support/binary/core_ext/io.rb +38 -0
  42. data/lib/ronin/support/binary/core_ext/string.rb +115 -0
  43. data/lib/ronin/{formatting/extensions/text.rb → support/binary/core_ext.rb} +9 -9
  44. data/lib/ronin/support/binary/cstring.rb +259 -0
  45. data/lib/ronin/support/binary/ctypes/aggregate_type.rb +98 -0
  46. data/lib/ronin/support/binary/ctypes/arch/arm/big_endian.rb +77 -0
  47. data/lib/ronin/support/binary/ctypes/arch/arm.rb +75 -0
  48. data/lib/ronin/support/binary/ctypes/arch/arm64/big_endian.rb +77 -0
  49. data/lib/ronin/support/binary/ctypes/arch/arm64.rb +75 -0
  50. data/lib/ronin/support/binary/ctypes/arch/mips/little_endian.rb +77 -0
  51. data/lib/ronin/support/binary/ctypes/arch/mips.rb +75 -0
  52. data/lib/ronin/support/binary/ctypes/arch/mips64/little_endian.rb +77 -0
  53. data/lib/ronin/support/binary/ctypes/arch/mips64.rb +75 -0
  54. data/lib/ronin/support/binary/ctypes/arch/ppc.rb +75 -0
  55. data/lib/ronin/support/binary/ctypes/arch/ppc64.rb +75 -0
  56. data/lib/ronin/support/binary/ctypes/arch/x86.rb +75 -0
  57. data/lib/ronin/support/binary/ctypes/arch/x86_64.rb +75 -0
  58. data/lib/ronin/support/binary/ctypes/arch.rb +30 -0
  59. data/lib/ronin/support/binary/ctypes/array_object_type.rb +164 -0
  60. data/lib/ronin/support/binary/ctypes/array_type.rb +232 -0
  61. data/lib/ronin/support/binary/ctypes/big_endian.rb +195 -0
  62. data/lib/ronin/support/binary/ctypes/char_type.rb +59 -0
  63. data/lib/ronin/support/binary/ctypes/char_types.rb +39 -0
  64. data/lib/ronin/support/binary/ctypes/enum_type.rb +181 -0
  65. data/lib/ronin/support/binary/ctypes/float32_type.rb +50 -0
  66. data/lib/ronin/support/binary/ctypes/float64_type.rb +50 -0
  67. data/lib/ronin/support/binary/ctypes/float_type.rb +62 -0
  68. data/lib/ronin/support/binary/ctypes/int16_type.rb +50 -0
  69. data/lib/ronin/support/binary/ctypes/int32_type.rb +50 -0
  70. data/lib/ronin/support/binary/ctypes/int64_type.rb +50 -0
  71. data/lib/ronin/support/binary/ctypes/int8_type.rb +41 -0
  72. data/lib/ronin/support/binary/ctypes/int_type.rb +62 -0
  73. data/lib/ronin/support/binary/ctypes/little_endian.rb +195 -0
  74. data/lib/ronin/support/binary/ctypes/mixin.rb +135 -0
  75. data/lib/ronin/support/binary/ctypes/native.rb +205 -0
  76. data/lib/ronin/support/binary/ctypes/network.rb +29 -0
  77. data/lib/ronin/support/binary/ctypes/object_type.rb +55 -0
  78. data/lib/ronin/support/binary/ctypes/os/bsd.rb +65 -0
  79. data/lib/ronin/support/binary/ctypes/os/freebsd.rb +215 -0
  80. data/lib/ronin/support/binary/ctypes/os/linux.rb +193 -0
  81. data/lib/ronin/support/binary/ctypes/os/macos.rb +151 -0
  82. data/lib/ronin/support/binary/ctypes/os/netbsd.rb +147 -0
  83. data/lib/ronin/support/binary/ctypes/os/openbsd.rb +168 -0
  84. data/lib/ronin/support/binary/ctypes/os/unix.rb +78 -0
  85. data/lib/ronin/support/binary/ctypes/os/windows.rb +125 -0
  86. data/lib/ronin/support/binary/ctypes/os.rb +125 -0
  87. data/lib/ronin/support/binary/ctypes/scalar_type.rb +200 -0
  88. data/lib/ronin/support/binary/ctypes/string_type.rb +143 -0
  89. data/lib/ronin/support/binary/ctypes/struct_object_type.rb +173 -0
  90. data/lib/ronin/support/binary/ctypes/struct_type.rb +359 -0
  91. data/lib/ronin/support/binary/ctypes/type.rb +193 -0
  92. data/lib/ronin/support/binary/ctypes/type_resolver.rb +206 -0
  93. data/lib/ronin/support/binary/ctypes/uint16_type.rb +50 -0
  94. data/lib/ronin/support/binary/ctypes/uint32_type.rb +50 -0
  95. data/lib/ronin/support/binary/ctypes/uint64_type.rb +50 -0
  96. data/lib/ronin/support/binary/ctypes/uint8_type.rb +41 -0
  97. data/lib/ronin/support/binary/ctypes/uint_type.rb +59 -0
  98. data/lib/ronin/support/binary/ctypes/unbounded_array_type.rb +258 -0
  99. data/lib/ronin/support/binary/ctypes/union_object_type.rb +173 -0
  100. data/lib/ronin/support/binary/ctypes/union_type.rb +261 -0
  101. data/lib/ronin/support/binary/ctypes.rb +462 -0
  102. data/lib/ronin/support/binary/hexdump/core_ext/file.rb +118 -0
  103. data/lib/ronin/support/binary/hexdump/core_ext/string.rb +115 -0
  104. data/lib/ronin/support/binary/hexdump/core_ext.rb +20 -0
  105. data/lib/ronin/support/binary/hexdump/parser.rb +492 -0
  106. data/lib/ronin/support/binary/hexdump.rb +20 -0
  107. data/lib/ronin/support/binary/memory.rb +268 -0
  108. data/lib/ronin/support/binary/packet.rb +33 -0
  109. data/lib/ronin/support/binary/stack.rb +256 -0
  110. data/lib/ronin/support/binary/stream/methods.rb +1755 -0
  111. data/lib/ronin/support/binary/stream.rb +151 -0
  112. data/lib/ronin/support/binary/struct/member.rb +86 -0
  113. data/lib/ronin/support/binary/struct.rb +830 -0
  114. data/lib/ronin/support/binary/template.rb +284 -0
  115. data/lib/ronin/support/binary/union.rb +162 -0
  116. data/lib/ronin/support/binary.rb +26 -0
  117. data/lib/ronin/support/cli/ansi.rb +330 -0
  118. data/lib/ronin/support/cli/io_shell/core_ext/io.rb +67 -0
  119. data/lib/ronin/{fuzzing/extensions.rb → support/cli/io_shell/core_ext.rb} +6 -7
  120. data/lib/ronin/support/cli/io_shell.rb +161 -0
  121. data/lib/ronin/support/cli/printing.rb +216 -0
  122. data/lib/ronin/support/cli.rb +20 -0
  123. data/lib/ronin/support/compression/core_ext/file.rb +70 -0
  124. data/lib/ronin/support/compression/core_ext/string.rb +101 -0
  125. data/lib/ronin/{formatting/html.rb → support/compression/core_ext.rb} +6 -7
  126. data/lib/ronin/support/compression/gzip/reader.rb +70 -0
  127. data/lib/ronin/support/compression/gzip/writer.rb +74 -0
  128. data/lib/ronin/support/compression/gzip.rb +105 -0
  129. data/lib/ronin/support/compression/mixin.rb +180 -0
  130. data/lib/ronin/{network/extensions/esmtp/net.rb → support/compression/zlib.rb} +9 -10
  131. data/lib/ronin/support/compression.rb +174 -0
  132. data/lib/ronin/{extensions → support/core_ext}/enumerable.rb +5 -6
  133. data/lib/ronin/{extensions → support/core_ext}/file.rb +11 -34
  134. data/lib/ronin/support/core_ext/integer.rb +37 -0
  135. data/lib/ronin/support/core_ext/ipaddr.rb +65 -0
  136. data/lib/ronin/{extensions → support/core_ext}/kernel.rb +10 -9
  137. data/lib/ronin/{extensions → support/core_ext}/resolv.rb +5 -28
  138. data/lib/ronin/{extensions → support/core_ext}/string.rb +117 -57
  139. data/lib/ronin/support/core_ext.rb +33 -0
  140. data/lib/ronin/support/crypto/cert.rb +522 -0
  141. data/lib/ronin/support/crypto/cert_chain.rb +204 -0
  142. data/lib/ronin/support/crypto/cipher/aes.rb +71 -0
  143. data/lib/ronin/support/crypto/cipher/aes128.rb +54 -0
  144. data/lib/ronin/support/crypto/cipher/aes256.rb +54 -0
  145. data/lib/ronin/support/crypto/cipher.rb +194 -0
  146. data/lib/ronin/support/crypto/core_ext/file.rb +660 -0
  147. data/lib/ronin/support/crypto/core_ext/string.rb +548 -0
  148. data/lib/ronin/{binary.rb → support/crypto/core_ext.rb} +7 -8
  149. data/lib/ronin/support/crypto/hmac.rb +48 -0
  150. data/lib/ronin/support/crypto/key/dh.rb +122 -0
  151. data/lib/ronin/support/crypto/key/dsa.rb +103 -0
  152. data/lib/ronin/support/crypto/key/ec.rb +99 -0
  153. data/lib/ronin/support/crypto/key/methods.rb +163 -0
  154. data/lib/ronin/support/crypto/key/rsa.rb +169 -0
  155. data/lib/ronin/support/crypto/key.rb +105 -0
  156. data/lib/ronin/support/crypto/mixin.rb +620 -0
  157. data/lib/ronin/{network/extensions/http/net.rb → support/crypto/openssl.rb} +9 -10
  158. data/lib/ronin/support/crypto.rb +779 -0
  159. data/lib/ronin/support/encoding/base16/core_ext/string.rb +63 -0
  160. data/lib/ronin/support/encoding/base16/core_ext.rb +19 -0
  161. data/lib/ronin/support/encoding/base16.rb +82 -0
  162. data/lib/ronin/support/encoding/base32/core_ext/string.rb +63 -0
  163. data/lib/ronin/support/encoding/base32/core_ext.rb +19 -0
  164. data/lib/ronin/support/encoding/base32.rb +164 -0
  165. data/lib/ronin/support/encoding/base64/core_ext/string.rb +76 -0
  166. data/lib/ronin/support/encoding/base64/core_ext.rb +19 -0
  167. data/lib/ronin/support/encoding/base64.rb +78 -0
  168. data/lib/ronin/support/encoding/c/core_ext/integer.rb +82 -0
  169. data/lib/ronin/support/encoding/c/core_ext/string.rb +125 -0
  170. data/lib/ronin/support/encoding/c/core_ext.rb +20 -0
  171. data/lib/ronin/support/encoding/c.rb +277 -0
  172. data/lib/ronin/support/encoding/core_ext/string.rb +107 -0
  173. data/lib/ronin/support/encoding/core_ext.rb +33 -0
  174. data/lib/ronin/support/encoding/hex/core_ext/integer.rb +82 -0
  175. data/lib/ronin/support/encoding/hex/core_ext/string.rb +133 -0
  176. data/lib/ronin/support/encoding/hex/core_ext.rb +22 -0
  177. data/lib/ronin/support/encoding/hex.rb +248 -0
  178. data/lib/ronin/support/encoding/html/core_ext/integer.rb +106 -0
  179. data/lib/ronin/support/encoding/html/core_ext/string.rb +130 -0
  180. data/lib/ronin/support/encoding/html/core_ext.rb +20 -0
  181. data/lib/ronin/support/encoding/html.rb +233 -0
  182. data/lib/ronin/support/encoding/http/core_ext/integer.rb +95 -0
  183. data/lib/ronin/support/encoding/http/core_ext/string.rb +129 -0
  184. data/lib/ronin/support/encoding/http/core_ext.rb +20 -0
  185. data/lib/ronin/support/encoding/http.rb +241 -0
  186. data/lib/ronin/support/encoding/js/core_ext/integer.rb +67 -0
  187. data/lib/ronin/support/encoding/js/core_ext/string.rb +125 -0
  188. data/lib/ronin/support/encoding/js/core_ext.rb +20 -0
  189. data/lib/ronin/support/encoding/js.rb +279 -0
  190. data/lib/ronin/support/encoding/powershell/core_ext/integer.rb +87 -0
  191. data/lib/ronin/support/encoding/powershell/core_ext/string.rb +145 -0
  192. data/lib/ronin/support/encoding/powershell/core_ext.rb +20 -0
  193. data/lib/ronin/support/encoding/powershell.rb +297 -0
  194. data/lib/ronin/support/encoding/punycode/core_ext/string.rb +63 -0
  195. data/lib/ronin/support/encoding/punycode/core_ext.rb +19 -0
  196. data/lib/ronin/support/encoding/punycode.rb +76 -0
  197. data/lib/ronin/support/encoding/quoted_printable/core_ext/string.rb +75 -0
  198. data/lib/ronin/support/encoding/quoted_printable/core_ext.rb +19 -0
  199. data/lib/ronin/support/encoding/quoted_printable.rb +102 -0
  200. data/lib/ronin/support/encoding/ruby/core_ext/string.rb +129 -0
  201. data/lib/ronin/{formatting/binary.rb → support/encoding/ruby/core_ext.rb} +6 -7
  202. data/lib/ronin/support/encoding/ruby.rb +235 -0
  203. data/lib/ronin/support/encoding/shell/core_ext/integer.rb +89 -0
  204. data/lib/ronin/support/encoding/shell/core_ext/string.rb +134 -0
  205. data/lib/ronin/support/encoding/shell/core_ext.rb +20 -0
  206. data/lib/ronin/support/encoding/shell.rb +293 -0
  207. data/lib/ronin/{network/extensions → support/encoding}/smtp.rb +7 -7
  208. data/lib/ronin/support/encoding/sql/core_ext/string.rb +114 -0
  209. data/lib/ronin/{formatting/http.rb → support/encoding/sql/core_ext.rb} +6 -7
  210. data/lib/ronin/support/encoding/sql.rb +124 -0
  211. data/lib/ronin/support/encoding/uri/core_ext/integer.rb +149 -0
  212. data/lib/ronin/support/encoding/uri/core_ext/string.rb +195 -0
  213. data/lib/ronin/support/encoding/uri/core_ext.rb +20 -0
  214. data/lib/ronin/support/encoding/uri.rb +424 -0
  215. data/lib/ronin/support/encoding/uuencoding/core_ext/string.rb +73 -0
  216. data/lib/ronin/support/encoding/uuencoding/core_ext.rb +19 -0
  217. data/lib/ronin/support/encoding/uuencoding.rb +70 -0
  218. data/lib/ronin/support/encoding/xml/core_ext/integer.rb +100 -0
  219. data/lib/ronin/support/encoding/xml/core_ext/string.rb +124 -0
  220. data/lib/ronin/support/encoding/xml/core_ext.rb +20 -0
  221. data/lib/ronin/support/encoding/xml.rb +328 -0
  222. data/lib/ronin/support/encoding.rb +46 -0
  223. data/lib/ronin/support/home.rb +88 -0
  224. data/lib/ronin/support/mixin.rb +42 -0
  225. data/lib/ronin/support/network/asn/dns_record.rb +112 -0
  226. data/lib/ronin/support/network/asn/list.rb +269 -0
  227. data/lib/ronin/support/network/asn/record.rb +164 -0
  228. data/lib/ronin/support/network/asn/record_set.rb +226 -0
  229. data/lib/ronin/support/network/asn.rb +88 -0
  230. data/lib/ronin/{binary/hexdump.rb → support/network/core_ext.rb} +6 -7
  231. data/lib/ronin/support/network/dns/idn.rb +38 -0
  232. data/lib/ronin/support/network/dns/mixin.rb +941 -0
  233. data/lib/ronin/support/network/dns/resolver.rb +707 -0
  234. data/lib/ronin/support/network/dns.rb +1109 -0
  235. data/lib/ronin/support/network/domain.rb +70 -0
  236. data/lib/ronin/support/network/email_address.rb +574 -0
  237. data/lib/ronin/support/network/esmtp/mixin.rb +115 -0
  238. data/lib/ronin/support/network/exceptions.rb +43 -0
  239. data/lib/ronin/support/network/ftp/mixin.rb +106 -0
  240. data/lib/ronin/support/network/host.rb +1473 -0
  241. data/lib/ronin/support/network/http/cookie.rb +245 -0
  242. data/lib/ronin/support/network/http/core_ext/uri/http.rb +63 -0
  243. data/lib/ronin/support/network/http/core_ext.rb +19 -0
  244. data/lib/ronin/support/network/http/mixin.rb +890 -0
  245. data/lib/ronin/support/network/http/request.rb +215 -0
  246. data/lib/ronin/support/network/http/set_cookie.rb +210 -0
  247. data/lib/ronin/support/network/http/user_agents.rb +115 -0
  248. data/lib/ronin/support/network/http.rb +2582 -0
  249. data/lib/ronin/support/network/imap/mixin.rb +133 -0
  250. data/lib/ronin/support/network/ip/mixin.rb +114 -0
  251. data/lib/ronin/support/network/ip.rb +540 -0
  252. data/lib/ronin/support/network/ip_range/cidr.rb +252 -0
  253. data/lib/ronin/support/network/ip_range/glob.rb +309 -0
  254. data/lib/ronin/support/network/ip_range/range.rb +249 -0
  255. data/lib/ronin/support/network/ip_range.rb +284 -0
  256. data/lib/ronin/support/network/mixin.rb +58 -0
  257. data/lib/ronin/support/network/packet.rb +27 -0
  258. data/lib/ronin/support/network/pop3/mixin.rb +113 -0
  259. data/lib/ronin/support/network/proxy.rb +602 -0
  260. data/lib/ronin/support/network/public_suffix/list.rb +339 -0
  261. data/lib/ronin/support/network/public_suffix/suffix.rb +118 -0
  262. data/lib/ronin/support/network/public_suffix/suffix_set.rb +150 -0
  263. data/lib/ronin/support/network/public_suffix.rb +41 -0
  264. data/lib/ronin/support/network/smtp/email.rb +190 -0
  265. data/lib/ronin/support/network/smtp/mixin.rb +290 -0
  266. data/lib/ronin/{extensions/meta.rb → support/network/smtp.rb} +6 -7
  267. data/lib/ronin/support/network/ssl/local_cert.rb +114 -0
  268. data/lib/ronin/support/network/ssl/local_key.rb +84 -0
  269. data/lib/ronin/support/network/ssl/mixin.rb +740 -0
  270. data/lib/ronin/{network/extensions/imap/net.rb → support/network/ssl/openssl.rb} +9 -10
  271. data/lib/ronin/support/network/ssl/proxy.rb +296 -0
  272. data/lib/ronin/support/network/ssl.rb +173 -0
  273. data/lib/ronin/support/network/tcp/mixin.rb +400 -0
  274. data/lib/ronin/support/network/tcp/proxy.rb +435 -0
  275. data/lib/ronin/support/network/tcp.rb +443 -0
  276. data/lib/ronin/support/network/telnet/mixin.rb +150 -0
  277. data/lib/ronin/support/network/telnet.rb +90 -0
  278. data/lib/ronin/support/network/tld/list.rb +266 -0
  279. data/lib/ronin/support/network/tld.rb +41 -0
  280. data/lib/ronin/support/network/tls/mixin.rb +670 -0
  281. data/lib/ronin/support/network/tls/proxy.rb +135 -0
  282. data/lib/ronin/support/network/tls.rb +53 -0
  283. data/lib/ronin/support/network/udp/mixin.rb +389 -0
  284. data/lib/ronin/support/network/udp/proxy.rb +192 -0
  285. data/lib/ronin/support/network/udp.rb +435 -0
  286. data/lib/ronin/support/network/unix/mixin.rb +273 -0
  287. data/lib/ronin/support/network.rb +37 -0
  288. data/lib/ronin/support/path.rb +136 -0
  289. data/lib/ronin/{network/extensions/dns/net.rb → support/text/core_ext/regexp.rb} +8 -9
  290. data/lib/ronin/support/text/core_ext/string.rb +46 -0
  291. data/lib/ronin/support/text/core_ext.rb +23 -0
  292. data/lib/ronin/support/text/entropy/core_ext/string.rb +45 -0
  293. data/lib/ronin/support/text/entropy/core_ext.rb +19 -0
  294. data/lib/ronin/support/text/entropy.rb +66 -0
  295. data/lib/ronin/support/text/erb/mixin.rb +44 -0
  296. data/lib/ronin/support/text/erb.rb +19 -0
  297. data/lib/ronin/support/text/homoglyph/core_ext/string.rb +108 -0
  298. data/lib/ronin/{formatting/digest.rb → support/text/homoglyph/core_ext.rb} +6 -7
  299. data/lib/ronin/{network/http/exceptions/unknown_request.rb → support/text/homoglyph/exceptions.rb} +10 -9
  300. data/lib/ronin/support/text/homoglyph/table.rb +228 -0
  301. data/lib/ronin/support/text/homoglyph.rb +142 -0
  302. data/lib/ronin/support/text/mixin.rb +31 -0
  303. data/lib/ronin/support/text/patterns/credentials.rb +75 -0
  304. data/lib/ronin/support/text/patterns/crypto.rb +67 -0
  305. data/lib/ronin/support/text/patterns/file_system.rb +93 -0
  306. data/lib/ronin/support/text/patterns/language.rb +37 -0
  307. data/lib/ronin/support/text/patterns/network/public_suffix.rb +44 -0
  308. data/lib/ronin/support/text/patterns/network.rb +140 -0
  309. data/lib/ronin/support/text/patterns/numeric.rb +52 -0
  310. data/lib/ronin/support/text/patterns/pii.rb +105 -0
  311. data/lib/ronin/support/text/patterns/source_code.rb +148 -0
  312. data/lib/ronin/support/text/patterns.rb +25 -0
  313. data/lib/ronin/support/text/random/mixin.rb +437 -0
  314. data/lib/ronin/support/text/random.rb +419 -0
  315. data/lib/ronin/support/text/typo/core_ext/string.rb +123 -0
  316. data/lib/ronin/support/text/typo/core_ext.rb +19 -0
  317. data/lib/ronin/support/text/typo/exceptions.rb +28 -0
  318. data/lib/ronin/support/text/typo/generator.rb +161 -0
  319. data/lib/ronin/support/text/typo.rb +260 -0
  320. data/lib/ronin/support/text.rb +26 -0
  321. data/lib/ronin/support/version.rb +6 -7
  322. data/lib/ronin/support.rb +20 -15
  323. data/ronin-support.gemspec +3 -1
  324. metadata +462 -369
  325. data/.gemtest +0 -0
  326. data/lib/ronin/binary/hexdump/parser.rb +0 -403
  327. data/lib/ronin/binary/struct.rb +0 -567
  328. data/lib/ronin/binary/template.rb +0 -454
  329. data/lib/ronin/extensions/ip_addr.rb +0 -217
  330. data/lib/ronin/extensions/meta/object.rb +0 -24
  331. data/lib/ronin/extensions/regexp.rb +0 -157
  332. data/lib/ronin/extensions.rb +0 -29
  333. data/lib/ronin/formatting/extensions/binary/array.rb +0 -61
  334. data/lib/ronin/formatting/extensions/binary/base64.rb +0 -106
  335. data/lib/ronin/formatting/extensions/binary/file.rb +0 -77
  336. data/lib/ronin/formatting/extensions/binary/float.rb +0 -65
  337. data/lib/ronin/formatting/extensions/binary/integer.rb +0 -180
  338. data/lib/ronin/formatting/extensions/binary/string.rb +0 -345
  339. data/lib/ronin/formatting/extensions/binary.rb +0 -26
  340. data/lib/ronin/formatting/extensions/digest/file.rb +0 -129
  341. data/lib/ronin/formatting/extensions/digest/string.rb +0 -86
  342. data/lib/ronin/formatting/extensions/digest.rb +0 -21
  343. data/lib/ronin/formatting/extensions/html/integer.rb +0 -142
  344. data/lib/ronin/formatting/extensions/html/string.rb +0 -194
  345. data/lib/ronin/formatting/extensions/html.rb +0 -21
  346. data/lib/ronin/formatting/extensions/http/integer.rb +0 -69
  347. data/lib/ronin/formatting/extensions/http/string.rb +0 -110
  348. data/lib/ronin/formatting/extensions/http.rb +0 -21
  349. data/lib/ronin/formatting/extensions/sql/string.rb +0 -128
  350. data/lib/ronin/formatting/extensions/sql.rb +0 -20
  351. data/lib/ronin/formatting/extensions/text/array.rb +0 -137
  352. data/lib/ronin/formatting/extensions/text/string.rb +0 -297
  353. data/lib/ronin/formatting/extensions.rb +0 -24
  354. data/lib/ronin/formatting/text.rb +0 -20
  355. data/lib/ronin/formatting.rb +0 -25
  356. data/lib/ronin/fuzzing/extensions/string.rb +0 -209
  357. data/lib/ronin/fuzzing/fuzzer.rb +0 -110
  358. data/lib/ronin/fuzzing/fuzzing.rb +0 -360
  359. data/lib/ronin/fuzzing/mutator.rb +0 -161
  360. data/lib/ronin/fuzzing/repeater.rb +0 -81
  361. data/lib/ronin/fuzzing/template.rb +0 -133
  362. data/lib/ronin/fuzzing.rb +0 -21
  363. data/lib/ronin/mixin.rb +0 -89
  364. data/lib/ronin/network/dns.rb +0 -201
  365. data/lib/ronin/network/esmtp.rb +0 -113
  366. data/lib/ronin/network/extensions/dns.rb +0 -20
  367. data/lib/ronin/network/extensions/esmtp.rb +0 -20
  368. data/lib/ronin/network/extensions/http/uri/http.rb +0 -228
  369. data/lib/ronin/network/extensions/http.rb +0 -21
  370. data/lib/ronin/network/extensions/imap.rb +0 -20
  371. data/lib/ronin/network/extensions/pop3/net.rb +0 -24
  372. data/lib/ronin/network/extensions/pop3.rb +0 -20
  373. data/lib/ronin/network/extensions/smtp/net.rb +0 -24
  374. data/lib/ronin/network/extensions/ssl/net.rb +0 -24
  375. data/lib/ronin/network/extensions/ssl.rb +0 -20
  376. data/lib/ronin/network/extensions/tcp/net.rb +0 -24
  377. data/lib/ronin/network/extensions/tcp.rb +0 -20
  378. data/lib/ronin/network/extensions/telnet/net.rb +0 -24
  379. data/lib/ronin/network/extensions/telnet.rb +0 -20
  380. data/lib/ronin/network/extensions/udp/net.rb +0 -24
  381. data/lib/ronin/network/extensions/udp.rb +0 -20
  382. data/lib/ronin/network/extensions.rb +0 -29
  383. data/lib/ronin/network/ftp.rb +0 -149
  384. data/lib/ronin/network/http/exceptions.rb +0 -20
  385. data/lib/ronin/network/http/http.rb +0 -1127
  386. data/lib/ronin/network/http/proxy.rb +0 -330
  387. data/lib/ronin/network/http.rb +0 -22
  388. data/lib/ronin/network/imap.rb +0 -158
  389. data/lib/ronin/network/mixins/dns.rb +0 -55
  390. data/lib/ronin/network/mixins/esmtp.rb +0 -164
  391. data/lib/ronin/network/mixins/ftp.rb +0 -155
  392. data/lib/ronin/network/mixins/http.rb +0 -227
  393. data/lib/ronin/network/mixins/imap.rb +0 -156
  394. data/lib/ronin/network/mixins/mixin.rb +0 -58
  395. data/lib/ronin/network/mixins/pop3.rb +0 -149
  396. data/lib/ronin/network/mixins/smtp.rb +0 -159
  397. data/lib/ronin/network/mixins/ssl.rb +0 -148
  398. data/lib/ronin/network/mixins/tcp.rb +0 -368
  399. data/lib/ronin/network/mixins/telnet.rb +0 -208
  400. data/lib/ronin/network/mixins/udp.rb +0 -381
  401. data/lib/ronin/network/mixins/unix.rb +0 -279
  402. data/lib/ronin/network/mixins.rb +0 -29
  403. data/lib/ronin/network/network.rb +0 -45
  404. data/lib/ronin/network/pop3.rb +0 -124
  405. data/lib/ronin/network/proxy.rb +0 -578
  406. data/lib/ronin/network/smtp/email.rb +0 -174
  407. data/lib/ronin/network/smtp/smtp.rb +0 -230
  408. data/lib/ronin/network/smtp.rb +0 -22
  409. data/lib/ronin/network/ssl.rb +0 -186
  410. data/lib/ronin/network/tcp/proxy.rb +0 -417
  411. data/lib/ronin/network/tcp/tcp.rb +0 -443
  412. data/lib/ronin/network/tcp.rb +0 -21
  413. data/lib/ronin/network/telnet.rb +0 -264
  414. data/lib/ronin/network/udp/proxy.rb +0 -191
  415. data/lib/ronin/network/udp/udp.rb +0 -450
  416. data/lib/ronin/network/udp.rb +0 -21
  417. data/lib/ronin/network/unix.rb +0 -286
  418. data/lib/ronin/network.rb +0 -31
  419. data/lib/ronin/path.rb +0 -137
  420. data/lib/ronin/spec/ui/output.rb +0 -22
  421. data/lib/ronin/support/inflector.rb +0 -92
  422. data/lib/ronin/support/support.rb +0 -42
  423. data/lib/ronin/templates/erb.rb +0 -78
  424. data/lib/ronin/templates/template.rb +0 -169
  425. data/lib/ronin/templates.rb +0 -21
  426. data/lib/ronin/ui/output/helpers.rb +0 -296
  427. data/lib/ronin/ui/output/output.rb +0 -146
  428. data/lib/ronin/ui/output/terminal/color.rb +0 -124
  429. data/lib/ronin/ui/output/terminal/raw.rb +0 -103
  430. data/lib/ronin/ui/output/terminal.rb +0 -21
  431. data/lib/ronin/ui/output.rb +0 -21
  432. data/lib/ronin/ui/shell.rb +0 -286
  433. data/lib/ronin/wordlist.rb +0 -287
  434. data/spec/binary/hexdump/helpers/hexdumps/ascii.bin +0 -0
  435. data/spec/binary/hexdump/helpers/hexdumps/hexdump_decimal_shorts.txt +0 -17
  436. data/spec/binary/hexdump/helpers/hexdumps/hexdump_hex_bytes.txt +0 -17
  437. data/spec/binary/hexdump/helpers/hexdumps/hexdump_hex_shorts.txt +0 -17
  438. data/spec/binary/hexdump/helpers/hexdumps/hexdump_octal_bytes.txt +0 -17
  439. data/spec/binary/hexdump/helpers/hexdumps/hexdump_octal_shorts.txt +0 -17
  440. data/spec/binary/hexdump/helpers/hexdumps/hexdump_repeated.txt +0 -6
  441. data/spec/binary/hexdump/helpers/hexdumps/od_decimal_bytes.txt +0 -17
  442. data/spec/binary/hexdump/helpers/hexdumps/od_decimal_ints.txt +0 -17
  443. data/spec/binary/hexdump/helpers/hexdumps/od_decimal_quads.txt +0 -17
  444. data/spec/binary/hexdump/helpers/hexdumps/od_decimal_shorts.txt +0 -17
  445. data/spec/binary/hexdump/helpers/hexdumps/od_doubles.txt +0 -17
  446. data/spec/binary/hexdump/helpers/hexdumps/od_floats.txt +0 -17
  447. data/spec/binary/hexdump/helpers/hexdumps/od_hex_bytes.txt +0 -17
  448. data/spec/binary/hexdump/helpers/hexdumps/od_hex_ints.txt +0 -17
  449. data/spec/binary/hexdump/helpers/hexdumps/od_hex_quads.txt +0 -17
  450. data/spec/binary/hexdump/helpers/hexdumps/od_hex_shorts.txt +0 -17
  451. data/spec/binary/hexdump/helpers/hexdumps/od_named_chars.txt +0 -17
  452. data/spec/binary/hexdump/helpers/hexdumps/od_octal_bytes.txt +0 -17
  453. data/spec/binary/hexdump/helpers/hexdumps/od_octal_ints.txt +0 -17
  454. data/spec/binary/hexdump/helpers/hexdumps/od_octal_quads.txt +0 -17
  455. data/spec/binary/hexdump/helpers/hexdumps/od_octal_shorts.txt +0 -17
  456. data/spec/binary/hexdump/helpers/hexdumps/od_repeated.txt +0 -6
  457. data/spec/binary/hexdump/helpers/hexdumps/repeated.bin +0 -1
  458. data/spec/binary/hexdump/helpers/hexdumps.rb +0 -13
  459. data/spec/binary/hexdump/parser_spec.rb +0 -302
  460. data/spec/binary/struct_spec.rb +0 -496
  461. data/spec/binary/template_spec.rb +0 -414
  462. data/spec/extensions/enumerable_spec.rb +0 -24
  463. data/spec/extensions/file_spec.rb +0 -63
  464. data/spec/extensions/ip_addr_spec.rb +0 -203
  465. data/spec/extensions/kernel_spec.rb +0 -30
  466. data/spec/extensions/regexp_spec.rb +0 -482
  467. data/spec/extensions/resolv_spec.rb +0 -18
  468. data/spec/extensions/string_spec.rb +0 -179
  469. data/spec/formatting/binary/array_spec.rb +0 -26
  470. data/spec/formatting/binary/base64_spec.rb +0 -50
  471. data/spec/formatting/binary/float_spec.rb +0 -34
  472. data/spec/formatting/binary/integer_spec.rb +0 -166
  473. data/spec/formatting/binary/string_spec.rb +0 -197
  474. data/spec/formatting/digest/string_spec.rb +0 -82
  475. data/spec/formatting/html/integer_spec.rb +0 -66
  476. data/spec/formatting/html/string_spec.rb +0 -103
  477. data/spec/formatting/http/integer_spec.rb +0 -42
  478. data/spec/formatting/http/string_spec.rb +0 -76
  479. data/spec/formatting/sql/string_spec.rb +0 -75
  480. data/spec/formatting/text/array_spec.rb +0 -105
  481. data/spec/formatting/text/string_spec.rb +0 -162
  482. data/spec/fuzzing/extensions/string_spec.rb +0 -87
  483. data/spec/fuzzing/fuzzer_spec.rb +0 -109
  484. data/spec/fuzzing/fuzzing_spec.rb +0 -24
  485. data/spec/fuzzing/mutator_spec.rb +0 -112
  486. data/spec/fuzzing/repeater_spec.rb +0 -57
  487. data/spec/fuzzing/template_spec.rb +0 -54
  488. data/spec/mixin_spec.rb +0 -53
  489. data/spec/network/dns_spec.rb +0 -201
  490. data/spec/network/ftp_spec.rb +0 -81
  491. data/spec/network/http/http_spec.rb +0 -466
  492. data/spec/network/http/proxy_spec.rb +0 -148
  493. data/spec/network/network_spec.rb +0 -8
  494. data/spec/network/proxy_spec.rb +0 -121
  495. data/spec/network/shared/unix_server.rb +0 -31
  496. data/spec/network/smtp/email_spec.rb +0 -100
  497. data/spec/network/ssl_spec.rb +0 -70
  498. data/spec/network/tcp/proxy_spec.rb +0 -116
  499. data/spec/network/tcp/tcp_spec.rb +0 -273
  500. data/spec/network/telnet_spec.rb +0 -67
  501. data/spec/network/udp/udp_spec.rb +0 -271
  502. data/spec/network/unix_spec.rb +0 -183
  503. data/spec/path_spec.rb +0 -86
  504. data/spec/spec_helper.rb +0 -9
  505. data/spec/support/inflector_spec.rb +0 -22
  506. data/spec/support_spec.rb +0 -8
  507. data/spec/templates/classes/example_erb.rb +0 -11
  508. data/spec/templates/classes/example_template.rb +0 -35
  509. data/spec/templates/erb_spec.rb +0 -21
  510. data/spec/templates/helpers/data/includes/_relative.erb +0 -1
  511. data/spec/templates/helpers/data/templates/example.erb +0 -1
  512. data/spec/templates/helpers/data.rb +0 -9
  513. data/spec/templates/template_spec.rb +0 -54
  514. data/spec/ui/classes/test_shell.rb +0 -22
  515. data/spec/ui/output_spec.rb +0 -32
  516. data/spec/ui/shell_spec.rb +0 -83
  517. data/spec/wordlist_spec.rb +0 -151
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Copyright (c) 2006-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
4
+ #
5
+ # ronin-support is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU Lesser General Public License as published
7
+ # by the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # ronin-support is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with ronin-support. If not, see <https://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ require 'ronin/support/network/host'
20
+
21
+ module Ronin
22
+ module Support
23
+ module Network
24
+ #
25
+ # Represents a domain.
26
+ #
27
+ # ## Examples
28
+ #
29
+ # domain = Domain.new('github.com')
30
+ # domain.ips
31
+ # # => [#<Ronin::Support::Network::IP: 192.30.255.113>]
32
+ # domain.ip
33
+ # # => #<Ronin::Support::Network::IP: 192.30.255.113>
34
+ # domain.mailservers
35
+ # # => ["aspmx.l.google.com",
36
+ # "alt3.aspmx.l.google.com",
37
+ # "alt4.aspmx.l.google.com",
38
+ # "alt1.aspmx.l.google.com",
39
+ # "alt2.aspmx.l.google.com"]
40
+ # domain.nameservers
41
+ # # => ["dns1.p08.nsone.net",
42
+ # "dns2.p08.nsone.net",
43
+ # "dns3.p08.nsone.net",
44
+ # "dns4.p08.nsone.net",
45
+ # "ns-1283.awsdns-32.org",
46
+ # "ns-1707.awsdns-21.co.uk",
47
+ # "ns-421.awsdns-52.com",
48
+ # "ns-520.awsdns-01.net"]
49
+ # domain.txt_strings
50
+ # # => ["v=spf1 ip4:192.30.252.0/22 include:_netblocks.google.com include:_netblocks2.google.com include:_netblocks3.google.com include:spf.protection.outlook.com include:mail.zendesk.com include:_spf.salesforce.com include:servers.mcsv.net ip4:166.78.69.169 ip4:1",
51
+ # "66.78.69.170 ip4:166.78.71.131 ip4:167.89.101.2 ip4:167.89.101.192/28 ip4:192.254.112.60 ip4:192.254.112.98/31 ip4:192.254.113.10 ip4:192.254.113.101 ip4:192.254.114.176 ip4:62.253.227.114 ~all",
52
+ # "MS=6BF03E6AF5CB689E315FB6199603BABF2C88D805",
53
+ # "MS=ms44452932",
54
+ # "atlassian-domain-verification=jjgw98AKv2aeoYFxiL/VFaoyPkn3undEssTRuMg6C/3Fp/iqhkV4HVV7WjYlVeF8",
55
+ # "stripe-verification=f88ef17321660a01bab1660454192e014defa29ba7b8de9633c69d6b4912217f",
56
+ # "google-site-verification=UTM-3akMgubp6tQtgEuAkYNYLyYAvpTnnSrDMWoDR3o",
57
+ # "MS=ms58704441",
58
+ # "docusign=087098e3-3d46-47b7-9b4e-8a23028154cd",
59
+ # "adobe-idp-site-verification=b92c9e999aef825edc36e0a3d847d2dbad5b2fc0e05c79ddd7a16139b48ecf4b",
60
+ # "apple-domain-verification=RyQhdzTl6Z6x8ZP4"]
61
+ #
62
+ # @api public
63
+ #
64
+ # @since 1.0.0
65
+ #
66
+ class Domain < Host
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,574 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Copyright (c) 2006-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
4
+ #
5
+ # ronin-support is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU Lesser General Public License as published
7
+ # by the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # ronin-support is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with ronin-support. If not, see <https://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ require 'ronin/support/network/exceptions'
20
+
21
+ module Ronin
22
+ module Support
23
+ module Network
24
+ #
25
+ # Represents an email address.
26
+ #
27
+ # ## Features
28
+ #
29
+ # * Supports normalizing tagged emails.
30
+ # * Supports {EmailAddress.deobfuscate deobfuscating} email addresses.
31
+ # * Supports {EmailAddress#obfuscate obfuscating} email addresses.
32
+ #
33
+ # ## Examples
34
+ #
35
+ # Builds a new email address:
36
+ #
37
+ # email = EmailAddress.new(mailbox: 'john.smith', domain: 'example.com')
38
+ #
39
+ # Parses an email address:
40
+ #
41
+ # email = EmailAddress.parse("John Smith <john.smith@example.com>")
42
+ # # => #<Ronin::Support::Network::EmailAddress:0x00007f49586d6a20
43
+ # @address=nil,
44
+ # @domain="example.com",
45
+ # @mailbox="john.smith",
46
+ # @name="John Smith",
47
+ # @routing=nil,
48
+ # @tag=nil>
49
+ #
50
+ # Deobfuscate an obfuscated email address:
51
+ #
52
+ # EmailAddress.deobfuscate("john[dot]smith [at] example[dot]com")
53
+ # # => "john.smith@example.com"
54
+ #
55
+ # Obfuscate an email address:
56
+ #
57
+ # email = EmailAddress.parse("john.smith@example.com")
58
+ # email.obfuscate
59
+ # # => "john <dot> smith <at> example <dot> com"
60
+ #
61
+ # Get every obfuscation of an email address:
62
+ #
63
+ # email.obfuscations
64
+ # # => ["john.smith AT example.com",
65
+ # # "john.smith at example.com",
66
+ # # "john.smith[AT]example.com",
67
+ # # "john.smith[at]example.com",
68
+ # # "john.smith [AT] example.com",
69
+ # # "john.smith [at] example.com",
70
+ # # "john.smith<AT>example.com",
71
+ # # "john.smith<at>example.com",
72
+ # # "john.smith <AT> example.com",
73
+ # # "john.smith <at> example.com",
74
+ # # "john.smith{AT}example.com",
75
+ # # "john.smith{at}example.com",
76
+ # # "john.smith {AT} example.com",
77
+ # # "john.smith {at} example.com",
78
+ # # "john.smith(AT)example.com",
79
+ # # "john.smith(at)example.com",
80
+ # # "john.smith (AT) example.com",
81
+ # # "john.smith (at) example.com",
82
+ # # "john DOT smith AT example DOT com",
83
+ # # "john dot smith at example dot com",
84
+ # # "john[DOT]smith[AT]example[DOT]com",
85
+ # # "john[dot]smith[at]example[dot]com",
86
+ # # "john [DOT] smith [AT] example [DOT] com",
87
+ # # "john [dot] smith [at] example [dot] com",
88
+ # # "john<DOT>smith<AT>example<DOT>com",
89
+ # # "john<dot>smith<at>example<dot>com",
90
+ # # "john <DOT> smith <AT> example <DOT> com",
91
+ # # "john <dot> smith <at> example <dot> com",
92
+ # # "john{DOT}smith{AT}example{DOT}com",
93
+ # # "john{dot}smith{at}example{dot}com",
94
+ # # "john {DOT} smith {AT} example {DOT} com",
95
+ # # "john {dot} smith {at} example {dot} com",
96
+ # # "john(DOT)smith(AT)example(DOT)com",
97
+ # # "john(dot)smith(at)example(dot)com",
98
+ # # "john (DOT) smith (AT) example (DOT) com",
99
+ # # "john (dot) smith (at) example (dot) com"]
100
+ #
101
+ # @see https://datatracker.ietf.org/doc/html/rfc2822#section-3.4
102
+ #
103
+ # @api public
104
+ #
105
+ # @since 1.0.0
106
+ #
107
+ class EmailAddress
108
+
109
+ # The optional name associated with the email address
110
+ # (ex: `John Smith <john.smith@example.com`).
111
+ #
112
+ # @return [String, nil]
113
+ attr_reader :name
114
+
115
+ # The mailbox or username of the email address.
116
+ #
117
+ # @return [String]
118
+ attr_reader :mailbox
119
+
120
+ alias username mailbox
121
+
122
+ # The optional sorting tag of the email address
123
+ # (ex: `john.smith+tag@example.com`).
124
+ #
125
+ # @return [String, nil]
126
+ attr_reader :tag
127
+
128
+ # Additional hosts to route sent emails through; aka the "percent hack"
129
+ # (ex: `john.smith%host3.com%host2.com@host1.com`).
130
+ #
131
+ # @return [Array<String>, nil]
132
+ attr_reader :routing
133
+
134
+ # The domain of the email address (ex: `john.smith@example.com`).
135
+ #
136
+ # @return [String, nil]
137
+ attr_reader :domain
138
+
139
+ # The IP address of the email address (ex: `john.smith@[1.2.3.4]`).
140
+ #
141
+ # @return [String, nil]
142
+ attr_reader :address
143
+
144
+ #
145
+ # Initializes the email address.
146
+ #
147
+ # @param [String, nil] name
148
+ # The optional name associated with the email address
149
+ # (ex: `John Smith <john.smith@example.com`).
150
+ #
151
+ # @param [String] mailbox
152
+ # The mailbox or username of the email address.
153
+ #
154
+ # @param [String, nil] tag
155
+ # The optional sorting tag of the email address
156
+ # (ex: `john.smith+tag@example.com`).
157
+ #
158
+ # @param [Array<String>, nil] routing
159
+ # Additional hosts to route sent emails through; aka the
160
+ # "percent hack" (ex: `john.smith%host3.com%host2.com@host1.com`).
161
+ #
162
+ # @param [String, nil] domain
163
+ # The domain of the email address (ex: `john.smith@example.com`).
164
+ #
165
+ # @param [String, nil] address
166
+ # The IP address of the email address (ex: `john.smith@[1.2.3.4]`).
167
+ #
168
+ # @raise [ArgumentError]
169
+ # Must specify either the `domain:` or `address:` keyword arguments.
170
+ #
171
+ # @example Initializing a basic email address.
172
+ # email = EmailAddress.new(mailbox: 'john.smith', domain: 'example.com')
173
+ #
174
+ # @example Initializing an email address with a name:
175
+ # email = EmailAddress.new(name: 'John Smith', mailbox: 'john.smith', domain: 'example.com')
176
+ #
177
+ # @example Initializing an email address with a sorting tag:
178
+ # email = EmailAddress.new(mailbox: 'john.smith', tag: 'spam', domain: 'example.com')
179
+ #
180
+ def initialize(name: nil, mailbox: , tag: nil, routing: nil, domain: nil, address: nil)
181
+ @name = name
182
+ @mailbox = mailbox
183
+ @tag = tag
184
+ @routing = routing
185
+
186
+ unless (domain.nil? ^ address.nil?)
187
+ raise(ArgumentError,"must specify domain: or address: keyword arguments")
188
+ end
189
+
190
+ @domain = domain
191
+ @address = address
192
+ end
193
+
194
+ #
195
+ # Parses an email address.
196
+ #
197
+ # @param [String] string
198
+ # The email string to parse.
199
+ #
200
+ # @return [EmailAddress]
201
+ # The parsed email address.
202
+ #
203
+ # @raise [InvalidEmailAddress]
204
+ # The string is not a valid formatted email address.
205
+ #
206
+ # @example
207
+ # email = EmailAddress.parse("John Smith <john.smith@example.com>")
208
+ # # => #<Ronin::Support::Network::EmailAddress:0x00007f49586d6a20
209
+ # @address=nil,
210
+ # @domain="example.com",
211
+ # @mailbox="john.smith",
212
+ # @name="John Smith",
213
+ # @routing=nil,
214
+ # @tag=nil>
215
+ #
216
+ # @see https://datatracker.ietf.org/doc/html/rfc2822#section-3.4
217
+ #
218
+ def self.parse(string)
219
+ if string.include?('<') && string.end_with?('>')
220
+ # Name <local-part@domain.com>
221
+ if (match = string.match(/^([^<]+)\s+<([^>]+)>$/))
222
+ name = match[1]
223
+ address = match[2]
224
+ else
225
+ raise(InvalidEmailAddress,"invalid email address: #{string.inspect}")
226
+ end
227
+ else
228
+ name = nil
229
+ address = string
230
+ end
231
+
232
+ return new(name: name, **parse_address(address))
233
+ end
234
+
235
+ private
236
+
237
+ #
238
+ # Parses the address portion of an email address.
239
+ #
240
+ # @param [String] string
241
+ # the email address string to parse.
242
+ #
243
+ # @return [Hash{Symbol => Object}]
244
+ # Keyword arguments for {#initialize}.
245
+ #
246
+ # @raise [InvalidEmailAddress]
247
+ # The string did not contain a `@` character.
248
+ #
249
+ # @api private
250
+ #
251
+ def self.parse_address(string)
252
+ unless string.include?('@')
253
+ raise(InvalidEmailAddress,"invalid email address: #{string.inspect}")
254
+ end
255
+
256
+ # local-part@domain.com
257
+ local_part, domain = string.split('@',2)
258
+
259
+ return {**parse_local_part(local_part), **parse_domain(domain)}
260
+ end
261
+
262
+ #
263
+ # Parses the local-part portion of an email address.
264
+ #
265
+ # @param [String] string
266
+ # the local-part string to parse.
267
+ #
268
+ # @return [Hash{Symbol => Object}]
269
+ # Keyword arguments for {#initialize}.
270
+ #
271
+ # @api private
272
+ #
273
+ def self.parse_local_part(string)
274
+ routing = nil
275
+
276
+ if string.include?('%')
277
+ mailbox, *routing = string.split('%')
278
+ else
279
+ mailbox = string
280
+ routing = nil
281
+ end
282
+
283
+ return {routing: routing, **parse_mailbox(mailbox)}
284
+ end
285
+
286
+ #
287
+ # Parses the mailbox portion of an email address.
288
+ #
289
+ # @param [String] string
290
+ # The mailbox string to parse.
291
+ #
292
+ # @return [Hash{Symbol => Object}]
293
+ # Keyword arguments for {#initialize}.
294
+ #
295
+ # @api private
296
+ #
297
+ def self.parse_mailbox(string)
298
+ # extract any sorting-tags (ex: `user+service@domain.com`)
299
+ mailbox, tag = string.split('+',2)
300
+
301
+ return {mailbox: mailbox, tag: tag}
302
+ end
303
+
304
+ #
305
+ # Parses the domain portion of an email address.
306
+ #
307
+ # @param [String] string
308
+ # The domain portion to parse.
309
+ #
310
+ # @return [Hash{Symbol => Object}]
311
+ # Keyword arguments for {#initialize}.
312
+ #
313
+ # @api private
314
+ #
315
+ def self.parse_domain(string)
316
+ domain = nil
317
+ address = nil
318
+
319
+ # extract IP addresses from the domain part (ex: `user@[1.2.3.4]`)
320
+ if string.start_with?('[') && string.end_with?(']')
321
+ address = string[1..-2]
322
+ else
323
+ domain = string
324
+ end
325
+
326
+ return {domain: domain, address: address}
327
+ end
328
+
329
+ public
330
+
331
+ # Email address de-obfuscation rules.
332
+ DEOBFUSCATIONS = {
333
+ /\s+@\s+/ => '@',
334
+ /\s+(?:at|AT)\s+/ => '@',
335
+ /\s+(?:dot|DOT)\s+/ => '.',
336
+ /\s*\[(?:at|AT)\]\s*/ => '@',
337
+ /\s*\[(?:dot|DOT)\]\s*/ => '.',
338
+ /\s*\<(?:at|AT)\>\s*/ => '@',
339
+ /\s*\<(?:dot|DOT)\>\s*/ => '.',
340
+ /\s*\{(?:at|AT)\}\s*/ => '@',
341
+ /\s*\{(?:dot|DOT)\}\s*/ => '.',
342
+ /\s*\((?:at|AT)\)\s*/ => '@',
343
+ /\s*\((?:dot|DOT)\)\s*/ => '.'
344
+ }
345
+
346
+ #
347
+ # Deobfuscates an obfuscated email address.
348
+ #
349
+ # @param [String] string
350
+ # The obfuscated email address to deobfuscate.
351
+ #
352
+ # @return [String]
353
+ # The deobfuscated email address.
354
+ #
355
+ # @example
356
+ # EmailAddress.deobfuscate("john[dot]smith [at] example[dot]com")
357
+ # # => "john.smith@example.com"
358
+ #
359
+ def self.deobfuscate(string)
360
+ DEOBFUSCATIONS.each do |pattern,replace|
361
+ string = string.gsub(pattern,replace)
362
+ end
363
+
364
+ return string
365
+ end
366
+
367
+ #
368
+ # Creates a new email address without the {#tag} or {#routing}
369
+ # attribute.
370
+ #
371
+ # @return [EmailAddress]
372
+ # The new normalized email address object.
373
+ #
374
+ # @example
375
+ # email = EmailAddress.parse("John Smith <john.smith+spam@example.com>")
376
+ # email.normalize.to_s
377
+ # # => "john.smith@example.com"
378
+ #
379
+ def normalize
380
+ EmailAddress.new(
381
+ mailbox: mailbox,
382
+ domain: domain,
383
+ address: address
384
+ )
385
+ end
386
+
387
+ #
388
+ # The hostname to connect to.
389
+ #
390
+ # @return [String]
391
+ # The {#domain} or {#address}.
392
+ #
393
+ def hostname
394
+ @domain || @address
395
+ end
396
+
397
+ #
398
+ # Converts the email address back into a string.
399
+ #
400
+ # @return [String]
401
+ # The string representation of the email address.
402
+ #
403
+ # @example
404
+ # email = EmailAddress.parse("John Smith <john.smith+spam@example.com>")
405
+ # email.to_s
406
+ # # => "John Smith <john.smith+spam@example.com>"
407
+ #
408
+ def to_s
409
+ string = "#{@mailbox}"
410
+ string << "+#{@tag}" if @tag
411
+ string << "%#{@routing.join('%')}" if @routing
412
+ string << "@"
413
+ string << if @address then "[#{@address}]"
414
+ else @domain
415
+ end
416
+ string = "#{@name} <#{string}>" if @name
417
+ return string
418
+ end
419
+
420
+ alias to_str to_s
421
+
422
+ #
423
+ # @group Obfuscation Methods
424
+ #
425
+
426
+ # Email address obfuscation rules.
427
+ OBFUSCATIONS = [
428
+ [/\@/, {'@' => ' @ ' }],
429
+ [/\@/, {'@' => ' AT ' }],
430
+ [/\@/, {'@' => ' at ' }],
431
+ [/\@/, {'@' => '[AT]' }],
432
+ [/\@/, {'@' => '[at]' }],
433
+ [/\@/, {'@' => ' [AT] '}],
434
+ [/\@/, {'@' => ' [at] '}],
435
+ [/\@/, {'@' => '<AT>' }],
436
+ [/\@/, {'@' => '<at>' }],
437
+ [/\@/, {'@' => ' <AT> '}],
438
+ [/\@/, {'@' => ' <at> '}],
439
+ [/\@/, {'@' => '{AT}' }],
440
+ [/\@/, {'@' => '{at}' }],
441
+ [/\@/, {'@' => ' {AT} '}],
442
+ [/\@/, {'@' => ' {at} '}],
443
+ [/\@/, {'@' => '(AT)' }],
444
+ [/\@/, {'@' => '(at)' }],
445
+ [/\@/, {'@' => ' (AT) '}],
446
+ [/\@/, {'@' => ' (at) '}],
447
+ [/[\.\@]/, {'.' => ' DOT ', '@' => ' AT ' }],
448
+ [/[\.\@]/, {'.' => ' dot ', '@' => ' at ' }],
449
+ [/[\.\@]/, {'.' => '[DOT]', '@' => '[AT]' }],
450
+ [/[\.\@]/, {'.' => '[dot]', '@' => '[at]' }],
451
+ [/[\.\@]/, {'.' => ' [DOT] ', '@' => ' [AT] '}],
452
+ [/[\.\@]/, {'.' => ' [dot] ', '@' => ' [at] '}],
453
+ [/[\.\@]/, {'.' => '<DOT>', '@' => '<AT>' }],
454
+ [/[\.\@]/, {'.' => '<dot>', '@' => '<at>' }],
455
+ [/[\.\@]/, {'.' => ' <DOT> ', '@' => ' <AT> '}],
456
+ [/[\.\@]/, {'.' => ' <dot> ', '@' => ' <at> '}],
457
+ [/[\.\@]/, {'.' => '{DOT}', '@' => '{AT}' }],
458
+ [/[\.\@]/, {'.' => '{dot}', '@' => '{at}' }],
459
+ [/[\.\@]/, {'.' => ' {DOT} ', '@' => ' {AT} '}],
460
+ [/[\.\@]/, {'.' => ' {dot} ', '@' => ' {at} '}],
461
+ [/[\.\@]/, {'.' => '(DOT)', '@' => '(AT)' }],
462
+ [/[\.\@]/, {'.' => '(dot)', '@' => '(at)' }],
463
+ [/[\.\@]/, {'.' => ' (DOT) ', '@' => ' (AT) '}],
464
+ [/[\.\@]/, {'.' => ' (dot) ', '@' => ' (at) '}]
465
+ ]
466
+
467
+ #
468
+ # Obfuscates the email address.
469
+ #
470
+ # @return [String]
471
+ # A randomly obfuscated version of the email address.
472
+ #
473
+ # @see OBFUSCATIONS
474
+ #
475
+ # @example
476
+ # email = EmailAddress.parse("john.smith@example.com")
477
+ # email.obfuscate
478
+ # # => "john.smith [AT] example.com"
479
+ # email.obfuscate
480
+ # # => "john <dot> smith <at> example <dot> com"
481
+ #
482
+ def obfuscate
483
+ string = to_s
484
+ string.gsub!(*OBFUSCATIONS.sample)
485
+ return string
486
+ end
487
+
488
+ #
489
+ # Enumerates over each obfuscation of the email address.
490
+ #
491
+ # @yield [obfuscated]
492
+ # If a block is given, it will be passed every obfuscation of the
493
+ # email address.
494
+ #
495
+ # @yieldparam [String] obfuscated
496
+ # An obfuscated version of the email address.
497
+ #
498
+ # @return [Enumerator]
499
+ # If no block is given, an Enumerator will be returned.
500
+ #
501
+ # @example
502
+ # email = EmailAddress.parse("john.smith@example.com")
503
+ # email.each_obfuscation { |obfuscated_email| ... }
504
+ #
505
+ # @see OBFUSCATIONS
506
+ #
507
+ def each_obfuscation
508
+ return enum_for(__method__) unless block_given?
509
+
510
+ string = to_s
511
+
512
+ OBFUSCATIONS.each do |gsub_args|
513
+ yield string.gsub(*gsub_args)
514
+ end
515
+
516
+ return nil
517
+ end
518
+
519
+ #
520
+ # Returns every obfuscation of the email address.
521
+ #
522
+ # @return [Array<String>]
523
+ # The Array containing every obfuscation of the email address.
524
+ #
525
+ # @example
526
+ # email = EmailAddress.parse("john.smith@example.com")
527
+ # email.obfuscations
528
+ # # => ["john.smith AT example.com",
529
+ # # "john.smith at example.com",
530
+ # # "john.smith[AT]example.com",
531
+ # # "john.smith[at]example.com",
532
+ # # "john.smith [AT] example.com",
533
+ # # "john.smith [at] example.com",
534
+ # # "john.smith<AT>example.com",
535
+ # # "john.smith<at>example.com",
536
+ # # "john.smith <AT> example.com",
537
+ # # "john.smith <at> example.com",
538
+ # # "john.smith{AT}example.com",
539
+ # # "john.smith{at}example.com",
540
+ # # "john.smith {AT} example.com",
541
+ # # "john.smith {at} example.com",
542
+ # # "john.smith(AT)example.com",
543
+ # # "john.smith(at)example.com",
544
+ # # "john.smith (AT) example.com",
545
+ # # "john.smith (at) example.com",
546
+ # # "john DOT smith AT example DOT com",
547
+ # # "john dot smith at example dot com",
548
+ # # "john[DOT]smith[AT]example[DOT]com",
549
+ # # "john[dot]smith[at]example[dot]com",
550
+ # # "john [DOT] smith [AT] example [DOT] com",
551
+ # # "john [dot] smith [at] example [dot] com",
552
+ # # "john<DOT>smith<AT>example<DOT>com",
553
+ # # "john<dot>smith<at>example<dot>com",
554
+ # # "john <DOT> smith <AT> example <DOT> com",
555
+ # # "john <dot> smith <at> example <dot> com",
556
+ # # "john{DOT}smith{AT}example{DOT}com",
557
+ # # "john{dot}smith{at}example{dot}com",
558
+ # # "john {DOT} smith {AT} example {DOT} com",
559
+ # # "john {dot} smith {at} example {dot} com",
560
+ # # "john(DOT)smith(AT)example(DOT)com",
561
+ # # "john(dot)smith(at)example(dot)com",
562
+ # # "john (DOT) smith (AT) example (DOT) com",
563
+ # # "john (dot) smith (at) example (dot) com"]
564
+ #
565
+ # @see #each_obfuscation
566
+ #
567
+ def obfuscations
568
+ each_obfuscation.to_a
569
+ end
570
+
571
+ end
572
+ end
573
+ end
574
+ end