Skip to content
This repository was archived by the owner on Aug 16, 2024. It is now read-only.

Commit ee1851f

Browse files
committed
Initial commit
0 parents  commit ee1851f

8 files changed

+234
-0
lines changed

.gitattributes

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Auto detect text files and perform LF normalization
2+
* text=auto

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2018 Kent 'picat' Gruber
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Subzero
2+
❄️ Work-in-progress development of the _cool_ new SubFinder core API `V2`
3+
4+
# Why?
5+
`V1` of SubFinder's core API is actually not that bad. However, I decided I would try and re-work the design to attempt to improve it. The main motivating factor being to simplify the boilerplate to add new subdomain enumeration sources and utilize the `interface` type in golang.
6+
7+
# How can I help?
8+
Make an issue or pull request to this repository to improve it!
9+
10+
* Try running the tests.
11+
* Fix the tests.
12+
* Write some tests.
13+
* Ask questions about parts that confuse you.
14+
* Add documentation.
15+
* Provide solutions for better word choices in documentation.
16+
* Spellchecking is awesome.
17+
* Be creative!

enumeration_options.go

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package subzero
2+
3+
// EnumerationOptions provides all the data needed for subdomain
4+
// enumeration. This includes all the sources which will be
5+
// queried to find them.
6+
type EnumerationOptions struct {
7+
Sources []Source
8+
}
9+
10+
// HasSources checks if the EnumerationOptions have any source defined.
11+
func (opts *EnumerationOptions) HasSources() bool {
12+
if len(opts.Sources) == 0 {
13+
return false
14+
}
15+
return true
16+
}

enumeration_options_test.go

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package subzero
2+
3+
import "testing"
4+
import "fmt"
5+
6+
func TestEnumerationOptions(t *testing.T) {
7+
opts := EnumerationOptions{}
8+
if len(opts.Sources) != 0 {
9+
t.Error("new enumeration options doesn't have empty sources list")
10+
}
11+
}
12+
13+
func TestEnumerationOptionsHasSources(t *testing.T) {
14+
opts := EnumerationOptions{}
15+
if opts.HasSources() {
16+
t.Error("new enumeration options doesn't have empty sources list")
17+
}
18+
}
19+
20+
func ExampleEnumerationOptions() {
21+
opts := EnumerationOptions{}
22+
if opts.HasSources() {
23+
fmt.Println("sources found in options")
24+
} else {
25+
fmt.Println("sources not found in options")
26+
}
27+
// Output: sources not found in options
28+
}

result.go

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package subzero
2+
3+
// Result contains the information from any given
4+
// source. It's the Source author's job to set the
5+
// type when returning a result. Upon success, a
6+
// Source source should provide a string as the found
7+
// subdomain. Upon Failure, the source should provide an error.
8+
type Result struct {
9+
Type string
10+
Success string
11+
Failure error
12+
}
13+
14+
// IsSuccess checks if the Result has any failure before
15+
// determining if the result succeeded.
16+
func (r *Result) IsSuccess() bool {
17+
if r.Failure != nil {
18+
return false
19+
}
20+
return true
21+
}
22+
23+
// IsSuccess checks if the Result has any failure before
24+
// determining if the result failed.
25+
func (r *Result) IsFailure() bool {
26+
if r.Failure != nil {
27+
return true
28+
}
29+
return false
30+
}
31+
32+
// HasType checks if the Result has a type value set.
33+
func (r *Result) HasType() bool {
34+
if r.Type != "" {
35+
return true
36+
}
37+
return false
38+
}

result_test.go

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package subzero
2+
3+
import "testing"
4+
import "fmt"
5+
import "errors"
6+
import "reflect"
7+
8+
func TestResult(t *testing.T) {
9+
var units = []struct {
10+
exp Result
11+
got string
12+
}{
13+
{Result{Type: "example", Success: "info.bing.com"}, "info.bing.com"},
14+
{Result{Type: "example", Failure: errors.New("failed")}, "failed"},
15+
}
16+
for _, u := range units {
17+
if u.exp.Failure != nil {
18+
if !reflect.DeepEqual(u.exp.Failure.Error(), u.got) {
19+
t.Fatalf("expected '%v', got '%v'", u.exp, u.got)
20+
}
21+
} else {
22+
if !reflect.DeepEqual(u.exp.Success, u.got) {
23+
t.Fatalf("expected '%v', got '%v'", u.exp, u.got)
24+
}
25+
}
26+
}
27+
}
28+
29+
func TestResultIsSuccess(t *testing.T) {
30+
var units = []struct {
31+
exp Result
32+
got bool
33+
}{
34+
{Result{Type: "example", Success: "info.bing.com"}, true},
35+
{Result{Type: "example", Failure: errors.New("failed")}, false},
36+
}
37+
for _, u := range units {
38+
if u.exp.IsSuccess() != u.got {
39+
t.Fatalf("expected '%v', got '%v'", u.exp, u.got)
40+
}
41+
}
42+
}
43+
44+
func TestResultIsFailure(t *testing.T) {
45+
var units = []struct {
46+
exp Result
47+
got bool
48+
}{
49+
{Result{Type: "example", Success: "info.bing.com"}, false},
50+
{Result{Type: "example", Failure: errors.New("failed")}, true},
51+
}
52+
for _, u := range units {
53+
if u.exp.IsFailure() != u.got {
54+
t.Fatalf("expected '%v', got '%v'", u.exp, u.got)
55+
}
56+
}
57+
}
58+
59+
func TestResultHasType(t *testing.T) {
60+
var units = []struct {
61+
exp Result
62+
got bool
63+
}{
64+
{Result{Type: "example", Success: "info.bing.com"}, true},
65+
{Result{Type: "example", Failure: errors.New("failed")}, true},
66+
{Result{}, false},
67+
}
68+
for _, u := range units {
69+
if u.exp.HasType() != u.got {
70+
t.Fatalf("expected '%v', got '%v'", u.exp, u.got)
71+
}
72+
}
73+
}
74+
75+
func ExampleResult() {
76+
result := Result{Type: "example", Success: "info.bing.com"}
77+
if result.Failure != nil {
78+
fmt.Println(result.Type, ":", result.Failure)
79+
} else {
80+
fmt.Println(result.Type, ":", result.Success)
81+
}
82+
// Output: example : info.bing.com
83+
}
84+
85+
func ExampleResultIsSuccess() {
86+
result := Result{Success: "wiggle.github.com"}
87+
if result.IsSuccess() {
88+
fmt.Println(result.Success)
89+
}
90+
// Output: wiggle.github.com
91+
}
92+
93+
func ExampleResultIsFailure() {
94+
result := Result{Failure: errors.New("failed to party")}
95+
if result.IsFailure() {
96+
fmt.Println(result.Failure.Error())
97+
}
98+
// Output: failed to party
99+
}
100+
101+
func ExampleResultHasType() {
102+
result := Result{Type: "example"}
103+
fmt.Println(result.HasType())
104+
// Output: true
105+
}

source.go

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package subzero
2+
3+
// Source defines the minimum interface any
4+
// subdomain enumeration module should follow.
5+
type Source interface {
6+
ProcessDomain(string) <-chan *Result
7+
}

0 commit comments

Comments
 (0)