@cryptotaxi247 / kubo / commits / 5b142948a

seccat (to test sio)

Juan Batiz-Benet committed Dec 10, 2014 at 23:49 UTC 5b142948ab413ad20921a9d7ffdd00ffcdb6d693
3 files changed +292
cmd/seccat/.gitignore new
+1
@@ -0,0 +1 @@
1 +seccat
cmd/seccat/seccat.go new
+240
@@ -0,0 +1,240 @@
1 +// package main provides an implementation of netcat using the secio package.
2 +// This means the channel is encrypted (and MACed).
3 +// It is meant to exercise the spipe package.
4 +// Usage:
5 +// seccat [<local address>] <remote address>
6 +// seccat -l <local address>
7 +//
8 +// Address format is: [host]:port
9 +package main
10 +
11 +import (
12 + "errors"
13 + "flag"
14 + "fmt"
15 + "io"
16 + "net"
17 + "os"
18 + "os/signal"
19 + "syscall"
20 +
21 + ci "github.com/jbenet/go-ipfs/crypto"
22 + secio "github.com/jbenet/go-ipfs/crypto/secio"
23 + peer "github.com/jbenet/go-ipfs/peer"
24 + u "github.com/jbenet/go-ipfs/util"
25 +)
26 +
27 +var verbose = false
28 +
29 +// Usage prints out the usage of this module.
30 +// Assumes flags use go stdlib flag pacakage.
31 +var Usage = func() {
32 + text := `seccat - secure netcat in Go
33 +
34 +Usage:
35 +
36 + listen: %s [<local address>] <remote address>
37 + dial: %s -l <local address>
38 +
39 +Address format is Go's: [host]:port
40 +`
41 +
42 + fmt.Fprintf(os.Stderr, text, os.Args[0], os.Args[0])
43 + flag.PrintDefaults()
44 +}
45 +
46 +type args struct {
47 + listen bool
48 + verbose bool
49 + debug bool
50 + localAddr string
51 + remoteAddr string
52 + // keyfile string
53 + keybits int
54 +}
55 +
56 +func parseArgs() args {
57 + var a args
58 +
59 + // setup + parse flags
60 + flag.BoolVar(&a.listen, "listen", false, "listen for connections")
61 + flag.BoolVar(&a.listen, "l", false, "listen for connections (short)")
62 + flag.BoolVar(&a.verbose, "v", true, "verbose")
63 + flag.BoolVar(&a.debug, "debug", false, "debugging")
64 + // flag.StringVar(&a.keyfile, "key", "", "private key file")
65 + flag.IntVar(&a.keybits, "keybits", 2048, "num bits for generating private key")
66 + flag.Usage = Usage
67 + flag.Parse()
68 + osArgs := flag.Args()
69 +
70 + if len(osArgs) < 1 {
71 + exit("")
72 + }
73 +
74 + if a.verbose {
75 + out("verbose on")
76 + }
77 +
78 + if a.listen {
79 + a.localAddr = osArgs[0]
80 + } else {
81 + if len(osArgs) > 1 {
82 + a.localAddr = osArgs[0]
83 + a.remoteAddr = osArgs[1]
84 + } else {
85 + a.remoteAddr = osArgs[0]
86 + }
87 + }
88 +
89 + return a
90 +}
91 +
92 +func main() {
93 + args := parseArgs()
94 + verbose = args.verbose
95 + if args.debug {
96 + u.SetDebugLogging()
97 + }
98 +
99 + go func() {
100 + // wait until we exit.
101 + sigc := make(chan os.Signal, 1)
102 + signal.Notify(sigc, syscall.SIGABRT)
103 + <-sigc
104 + panic("ABORT! ABORT! ABORT!")
105 + }()
106 +
107 + if err := connect(args); err != nil {
108 + exit("%s", err)
109 + }
110 +}
111 +
112 +func setupPeer(a args) (peer.Peer, peer.Peerstore, error) {
113 + if a.keybits < 1024 {
114 + return nil, nil, errors.New("Bitsize less than 1024 is considered unsafe.")
115 + }
116 +
117 + out("generating key pair...")
118 + sk, pk, err := ci.GenerateKeyPair(ci.RSA, a.keybits)
119 + if err != nil {
120 + return nil, nil, err
121 + }
122 +
123 + ps := peer.NewPeerstore()
124 + peer, err := ps.WithKeyPair(sk, pk)
125 + if err != nil {
126 + return nil, nil, err
127 + }
128 + out("local peer id: %s", peer.ID())
129 + return peer, ps, nil
130 +}
131 +
132 +func connect(args args) error {
133 + p, ps, err := setupPeer(args)
134 + if err != nil {
135 + return err
136 + }
137 +
138 + var conn net.Conn
139 + if args.listen {
140 + conn, err = Listen(args.localAddr)
141 + } else {
142 + conn, err = Dial(args.localAddr, args.remoteAddr)
143 + }
144 + if err != nil {
145 + return err
146 + }
147 +
148 + // log everything that goes through conn
149 + rwc := &logRW{n: "conn", rw: conn}
150 +
151 + // OK, let's setup the channel.
152 + sg := secio.SessionGenerator{Local: p, Peerstore: ps}
153 + sess, err := sg.NewSession(nil, rwc)
154 + if err != nil {
155 + return err
156 + }
157 + out("remote peer id: %s", sess.RemotePeer().ID())
158 + netcat(sess.ReadWriter().(io.ReadWriteCloser))
159 + return nil
160 +}
161 +
162 +// Listen listens and accepts one incoming UDT connection on a given port,
163 +// and pipes all incoming data to os.Stdout.
164 +func Listen(localAddr string) (net.Conn, error) {
165 + l, err := net.Listen("tcp", localAddr)
166 + if err != nil {
167 + return nil, err
168 + }
169 + out("listening at %s", l.Addr())
170 +
171 + c, err := l.Accept()
172 + if err != nil {
173 + return nil, err
174 + }
175 + out("accepted connection from %s", c.RemoteAddr())
176 +
177 + // done with listener
178 + l.Close()
179 +
180 + return c, nil
181 +}
182 +
183 +// Dial connects to a remote address and pipes all os.Stdin to the remote end.
184 +// If localAddr is set, uses it to Dial from.
185 +func Dial(localAddr, remoteAddr string) (net.Conn, error) {
186 +
187 + var laddr net.Addr
188 + var err error
189 + if localAddr != "" {
190 + laddr, err = net.ResolveTCPAddr("tcp", localAddr)
191 + if err != nil {
192 + return nil, fmt.Errorf("failed to resolve address %s", localAddr)
193 + }
194 + }
195 +
196 + if laddr != nil {
197 + out("dialing %s from %s", remoteAddr, laddr)
198 + } else {
199 + out("dialing %s", remoteAddr)
200 + }
201 +
202 + d := net.Dialer{LocalAddr: laddr}
203 + c, err := d.Dial("tcp", remoteAddr)
204 + if err != nil {
205 + return nil, err
206 + }
207 + out("connected to %s", c.RemoteAddr())
208 +
209 + return c, nil
210 +}
211 +
212 +func netcat(c io.ReadWriteCloser) {
213 + out("piping stdio to connection")
214 +
215 + done := make(chan struct{}, 2)
216 +
217 + go func() {
218 + n, _ := io.Copy(c, os.Stdin)
219 + out("sent %d bytes", n)
220 + done <- struct{}{}
221 + }()
222 + go func() {
223 + n, _ := io.Copy(os.Stdout, c)
224 + out("received %d bytes", n)
225 + done <- struct{}{}
226 + }()
227 +
228 + // wait until we exit.
229 + sigc := make(chan os.Signal, 1)
230 + signal.Notify(sigc, syscall.SIGHUP, syscall.SIGINT,
231 + syscall.SIGTERM, syscall.SIGQUIT)
232 +
233 + select {
234 + case <-done:
235 + case <-sigc:
236 + return
237 + }
238 +
239 + c.Close()
240 +}
cmd/seccat/util.go new
+51
@@ -0,0 +1,51 @@
1 +package main
2 +
3 +import (
4 + "fmt"
5 + "io"
6 + "os"
7 +
8 + u "github.com/jbenet/go-ipfs/util"
9 +)
10 +
11 +var log = u.Logger("seccat")
12 +
13 +func exit(format string, vals ...interface{}) {
14 + if format != "" {
15 + fmt.Fprintf(os.Stderr, "seccat: error: "+format+"\n", vals...)
16 + }
17 + Usage()
18 + os.Exit(1)
19 +}
20 +
21 +func out(format string, vals ...interface{}) {
22 + if verbose {
23 + fmt.Fprintf(os.Stderr, "seccat: "+format+"\n", vals...)
24 + }
25 +}
26 +
27 +type logRW struct {
28 + n string
29 + rw io.ReadWriter
30 +}
31 +
32 +func (r *logRW) Read(buf []byte) (int, error) {
33 + n, err := r.rw.Read(buf)
34 + if err == nil {
35 + log.Debugf("%s read: %v", r.n, buf)
36 + }
37 + return n, err
38 +}
39 +
40 +func (r *logRW) Write(buf []byte) (int, error) {
41 + log.Debugf("%s write: %v", r.n, buf)
42 + return r.rw.Write(buf)
43 +}
44 +
45 +func (r *logRW) Close() error {
46 + c, ok := r.rw.(io.Closer)
47 + if ok {
48 + return c.Close()
49 + }
50 + return nil
51 +}