github.com/iDigitalFlame/xmt@v0.5.4/com/wc2/target.go (about) 1 // Copyright (C) 2020 - 2023 iDigitalFlame 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU General Public License as published by 5 // the Free Software Foundation, either version 3 of the License, or 6 // any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU General Public License for more details. 12 // 13 // You should have received a copy of the GNU General Public License 14 // along with this program. If not, see <https://www.gnu.org/licenses/>. 15 // 16 17 package wc2 18 19 import ( 20 "net/http" 21 22 "github.com/iDigitalFlame/xmt/util/text" 23 ) 24 25 // TargetEmpty is a Target that does not have anything set and will not mutate a 26 // Request. 27 var TargetEmpty Target 28 29 // Target is a struct that is composed of three separate Stringer interfaces. 30 // These are called via their 'String' function to specify the User-Agent, URL 31 // and Host string values. They can be set to static strings using the 32 // 'text.String' wrapper. This struct can be used as a C2 client connector. If 33 // the Client property is not set, the DefaultClient value will be used. 34 type Target struct { 35 URL, Host, Agent Stringer 36 Headers map[string]Stringer 37 } 38 39 // Stringer is a utility interface that takes a single 'String() string' 40 // function for returning a string to be used as a Target. 41 type Stringer interface { 42 String() string 43 } 44 45 // Reset sets all the Target values to nil. This allows for an empty Target to 46 // be used. 47 func (t *Target) Reset() { 48 if t.URL, t.Host, t.Agent = nil, nil, nil; t.Headers != nil && len(t.Headers) > 0 { 49 for k := range t.Headers { 50 delete(t.Headers, k) 51 } 52 } 53 } 54 55 // Rule will attempt to generate a Rule that matches this generator using the 56 // current configuration. 57 // 58 // Rules will only be added if the settings implement the 'MatchString(string) bool' 59 // function. Otherwise, the specified rule will attempt to match using a Text 60 // Matcher. 61 // 62 // Empty Target return an empty rule. 63 func (t Target) Rule() Rule { 64 var r Rule 65 if t.empty() { 66 return r 67 } 68 if t.URL != nil { 69 if m, ok := t.URL.(Matcher); ok { 70 r.URL = m 71 } else if m, ok := t.URL.(text.Matcher); ok { 72 r.URL = m.Match() 73 } else { 74 r.URL = text.Matcher(t.URL.String()).Match() 75 } 76 } 77 if t.Host != nil { 78 if m, ok := t.Host.(Matcher); ok { 79 r.Host = m 80 } else if m, ok := t.Host.(text.Matcher); ok { 81 r.Host = m.Match() 82 } else { 83 r.Host = text.Matcher(t.Host.String()).Match() 84 } 85 } 86 if t.Agent != nil { 87 if m, ok := t.Agent.(Matcher); ok { 88 r.Agent = m 89 } else if m, ok := t.Agent.(text.Matcher); ok { 90 r.Agent = m.Match() 91 } else { 92 r.Agent = text.Matcher(t.Agent.String()).Match() 93 } 94 } 95 if t.Headers != nil && len(t.Headers) > 0 { 96 r.Headers = make(map[string]Matcher, len(t.Headers)) 97 for k, v := range t.Headers { 98 if m, ok := v.(Matcher); ok { 99 r.Headers[k] = m 100 } else if m, ok := v.(text.Matcher); ok { 101 r.Headers[k] = m.Match() 102 } else { 103 r.Headers[k] = text.Matcher(v.String()).Match() 104 } 105 } 106 } 107 return r 108 } 109 func (t Target) empty() bool { 110 return t.Agent == nil && t.Host == nil && t.URL == nil && len(t.Headers) == 0 111 } 112 func (t *Target) mutate(r *http.Request) { 113 if t.URL != nil { 114 s := t.URL.String() 115 if len(s) > 0 && s[0] != '/' { 116 r.URL.Path = "/" + s 117 } else { 118 r.URL.Path = s 119 } 120 } 121 if t.Host != nil { 122 r.Host = t.Host.String() 123 } 124 if t.Agent != nil { 125 r.Header.Set(userAgent, t.Agent.String()) 126 } 127 for k, v := range t.Headers { 128 r.Header.Set(k, v.String()) 129 } 130 } 131 132 // Header adds the stringer to the Target's header set. 133 // 134 // This function will create the headers map if it's nil. 135 func (t *Target) Header(k string, v Stringer) { 136 if t.Headers == nil { 137 t.Headers = make(map[string]Stringer) 138 } 139 t.Headers[k] = v 140 }