CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/msf/core/exploit/git.rb
Views: 11784
1
# -*- coding: binary -*-
2
3
module Msf
4
5
# This mixin provides helper functions for building Git repositories
6
module Exploit::Git
7
8
class GitObject
9
10
attr_reader :type, :content, :sha1, :path, :compressed
11
12
def initialize(type, content, sha1, compressed)
13
@type = type
14
@content = content
15
@sha1 = sha1
16
@compressed = compressed
17
@path = "#{@sha1[0...2]}/#{@sha1[2..40]}"
18
end
19
20
# Wrapper for `build_object()` to create
21
# a GitObject of type `commit`
22
# @param [ Hash ] containing sha1s for the tree,
23
# (optional) parent sha1 and optional data
24
# such as commit message, committer name,
25
# company name, and email address
26
def self.build_commit_object(opts = {})
27
full_name = opts[:name] || Faker::Name.name
28
email = opts[:email] || Faker::Internet.email(name: full_name, separators: ['-', '_'])
29
company = opts[:company] || Faker::Company.name
30
commit_text = opts[:message] || "Initial commit to open git repository for #{company}!"
31
tree_sha1 = opts[:tree_sha1]
32
parent_sha1 = opts[:parent_sha1]
33
34
tstamp = Time.now.to_i
35
author_time = rand(tstamp)
36
commit_time = rand(author_time)
37
tz_off = rand(10)
38
39
commit_msg = "tree #{tree_sha1}\n"
40
commit_msg << "parent #{parent_sha1}\n" unless parent_sha1.nil?
41
commit_msg << "author #{full_name} <#{email}> #{author_time} -0#{tz_off}00\n"
42
commit_msg << "committer #{full_name} <#{email}> #{commit_time} -0#{tz_off}00\n"
43
commit_msg << "\n"
44
commit_msg << "#{commit_text}\n"
45
46
sha1, compressed = build_object('commit', commit_msg)
47
GitObject.new('commit', commit_msg, sha1, compressed)
48
end
49
50
# Wrapper for `build_object()` to create
51
# a GitObject of type `blob`
52
# @param [ String ] the data that the object
53
# will represent
54
def self.build_blob_object(content)
55
sha1, compressed = build_object('blob', content)
56
GitObject.new('blob', content, sha1, compressed)
57
end
58
59
# Creates a GitObject of type `tree`
60
# @param [ Hash ] entries containing
61
# the file mode, name, and sha1 from
62
# a previously-created `blob` object
63
# Ex:
64
# {
65
# mode: '100755', file_name: 'hooks',
66
# sha1: 'a372436ad8331b380e20e8c9861f547063d76a46'
67
# }
68
def self.build_tree_object(tree_entries)
69
tree = ''
70
unless tree_entries.is_a?(Array)
71
tree_entries = [ tree_entries ]
72
end
73
74
tree_entries.each do |entry|
75
tree += "#{entry[:mode]} #{entry[:file_name]}\0#{[entry[:sha1]].pack('H*')}"
76
end
77
78
sha1, compressed = build_object('tree', tree)
79
GitObject.new('tree', tree, sha1, compressed)
80
end
81
82
# Generates a git object of the specified
83
# type, ex: blob, tree, commit
84
#
85
# @param [ String ] type of object to create
86
# @param [ String ] the data that the resulting
87
# object will represent
88
# Returns an Array containing the sha1 hash
89
# and Zlib-compressed data
90
def self.build_object(type, content)
91
# taken from http://schacon.github.io/gitbook/7_how_git_stores_objects.html
92
header = "#{type} #{content.size}\0"
93
store = header + content
94
[Digest::SHA1.hexdigest(store), Rex::Text.zlib_deflate(store, Zlib::DEFAULT_COMPRESSION)]
95
end
96
97
# Given a sha1 and list of Git objects
98
# find the object with the matching sha1
99
#
100
# @param [ String ] sha1 of the object to find
101
# @param [ Array ] list of GitObjects to search
102
# @return GitObject with the matching sha1, nil otherwise
103
def self.find_object(sha1, objs = [])
104
return nil if objs.empty?
105
106
objs.find { |obj| obj.sha1 == sha1 }
107
end
108
end
109
end
110
end
111
112