func createMoldPacket(startSeqNum, count int) (bs []byte, err error) { defer errs.PassE(&err) type moldUDP64 struct { Session string `struc:"[10]byte"` SequenceNumber uint64 MessageCount uint16 } type moldUDP64MessageBlock struct { MessageLength int16 `struc:"sizeof=Payload"` Payload []uint8 } errs.Check(startSeqNum >= 0) errs.Check(count >= 0 && count < 1000) mh := moldUDP64{ Session: "00TestSess", SequenceNumber: uint64(startSeqNum), MessageCount: uint16(count), } var bb bytes.Buffer errs.CheckE(struc.Pack(&bb, &mh)) for i := 0; i < count; i++ { mb := moldUDP64MessageBlock{ Payload: generateIttoMessage(startSeqNum + i), } errs.CheckE(struc.Pack(&bb, &mb)) } bs = bb.Bytes() return }
func kissFinishHandshake(eph_priv natrium.ECDHPrivate, packaged kissSegment, check Verifier, transport io.ReadWriteCloser) (*kissContext, error) { signal := make(chan error, 1) // spawn new thread to prevent deadlock go func() { err := struc.Pack(transport, &packaged) if err != nil { fmt.Println(err.Error()) transport.Close() signal <- err } else { signal <- nil } }() // wait for other end var their_hello kissSegment err := struc.Unpack(transport, &their_hello) if err != nil { return nil, ErrFailHello } // wait for our end to finish (do not want to stomp with our response) err = <-signal if err != nil { return nil, err } // different types of hello var their_eph_pub natrium.ECDHPublic switch their_hello.Msgtyp { case kiss_AHLO: if check != nil { return nil, ErrWrongHello } their_eph_pub = their_hello.Payload case kiss_NHLO: var mss kissNamedHello err := struc.Unpack(bytes.NewBuffer(their_hello.Payload), &mss) if err != nil { fmt.Println(err.Error()) return nil, ErrBadHello } err = mss.Ltm_key.Verify(mss.Eph_key, mss.Signat) if err != nil { fmt.Println(err.Error()) return nil, ErrBadHello } if check != nil && check(mss.Ltm_key) == false { return nil, ErrBadExchange } their_eph_pub = mss.Eph_key default: fmt.Println(their_hello) return nil, ErrBadHello } return kissGenerateCtx(transport, eph_priv, their_eph_pub), nil }
func (seg *Segment) ToBytes() []byte { buf := new(bytes.Buffer) err := struc.Pack(buf, seg) if err != nil { panic(err.Error()) } return buf.Bytes() }
func TestStructs(t *testing.T) { var lol srvEdgeResp lol.Neighs = make([]Neighbor, 10) xaxa := new(bytes.Buffer) err := struc.Pack(xaxa, &lol) if err != nil { panic(err.Error()) } }
func Uname(u models.Usercorn, addr uint64, un *models.Uname) uint64 { struc.Pack(u.MemWriter(addr), un) /* var utsname syscall.Utsname if err := syscall.Uname(utsname); err != nil { return 1 } */ return 0 }
func fstat(u U, a []uint64) uint64 { fd, buf := int(a[0]), a[1] var stat syscall.Stat_t if err := syscall.Fstat(fd, &stat); err != nil { return errno(err) } if err := struc.Pack(u.Mem().StreamAt(buf), &stat); err != nil { panic(err) } return 0 }
// KiSSAnonHandshake does an anonymous KiSS handshake over the given transport, // validating the other end using the given verifier, which may be nil. // // Usually, clients use the anonymous handshake, while servers use the named handshake. func KiSSAnonHandshake(check Verifier, transport io.ReadWriteCloser) (io.ReadWriteCloser, error) { eph_priv := natrium.ECDHGenerateKey() // send AHLO message tosend := kissAnonHello{eph_priv.PublicKey()} buf := new(bytes.Buffer) struc.Pack(buf, &tosend) packaged := kissSegment{0, kiss_AHLO, append(make([]byte, 0), buf.Bytes()...)} return kissFinishHandshake(eph_priv, packaged, check, transport) }
func BenchmarkStructs(b *testing.B) { var lol srvEdgeResp lol.Neighs = make([]Neighbor, 10) xaxa := new(bytes.Buffer) for i := 0; i < b.N; i++ { err := struc.Pack(xaxa, &lol) err = struc.Unpack(xaxa, &lol) if err != nil { panic(err.Error()) } } }
func (ctx *kissContext) Write(p []byte) (int, error) { // sign data nonce := make([]byte, ctx.read_chug.NonceSize()) binary.LittleEndian.PutUint64(nonce, ctx.write_count) ctx.write_count++ load := ctx.write_chug.Seal(nil, nonce, p, []byte{kiss_DATA}) // send segment segm := kissSegment{0, kiss_DATA, load} err := struc.Pack(ctx.transport, &segm) return len(p), err }
// KiSSAnonHandshake does a named KiSS handshake over the given transport, // validating the other end using the given verifier, which may be nil. // // Usually, clients use the anonymous handshake, while servers use the named handshake. func KiSSNamedHandshake(identity natrium.EdDSAPrivate, check Verifier, transport io.ReadWriteCloser) (io.ReadWriteCloser, error) { eph_priv := natrium.ECDHGenerateKey() signat := identity.Sign(eph_priv.PublicKey()) // send NHLO message tosend := kissNamedHello{eph_priv.PublicKey(), signat, identity.PublicKey()} buf := new(bytes.Buffer) err := struc.Pack(buf, &tosend) if err != nil { panic(err.Error()) } packaged := kissSegment{0, kiss_NHLO, buf.Bytes()} return kissFinishHandshake(eph_priv, packaged, check, transport) }
func (cc *commonCtx) thrProcessUp() { for { select { case seg := <-cc.upch: err := struc.Pack(cc.carrier, &seg) if err != nil { cc.destroy(err) return } kilog.FineDebug("kiricom: commonCtx successfully transmitted %v", seg) case <-cc.deadch: return } } }
func stat(u U, a []uint64) uint64 { path, _ := u.Mem().ReadStrAt(a[0]) if strings.Contains(path, "/lib/") { path = u.PrefixPath(path, false) } buf := a[1] var stat syscall.Stat_t if err := syscall.Stat(path, &stat); err != nil { return errno(err) } if err := struc.Pack(u.Mem().StreamAt(buf), &stat); err != nil { panic(err) } return 0 }
func (ctx *kissContext) Close() error { // send close message msg := []byte("kthxbai") nonce := make([]byte, ctx.read_chug.NonceSize()) binary.LittleEndian.PutUint64(nonce, ctx.write_count) ctx.write_count++ load := ctx.write_chug.Seal(nil, nonce, msg, []byte{kiss_CLOS}) // send segment segm := kissSegment{0, kiss_CLOS, load} err := struc.Pack(ctx.transport, &segm) ctx.transport.Close() return err }
// GetDaemon searches for a running SAGIRI instance and returns a Daemon type. func GetDaemon() (toret Daemon, err error) { conn, err := net.Dial("tcp", "127.0.0.1:12377") // always on port 12377 if err != nil { return } err = struc.Unpack(conn, &toret) if err != nil { return } if toret.Magic != 0xCACACACA { err = errors.New("magic number not correct") return } var lol ctlCommand lol.Verb = ctlCmdNOOP struc.Pack(conn, &lol) return }
func (dpv dftProv) JoinCore(clnt Client) (err error) { sok := dpv.getSock(clnt) if sok == nil { err = errors.New("directory: default provider failed to obtain socket") return } defer sok.Close() // TODO why do we need to make this copy?????? xxx := make([]byte, 4) copy(xxx, clnt.addr.IP.To4()) req := clntRequest{ Code: "CORE", Address: xxx, Port: clnt.addr.Port, Secret: clnt.obfsec, PubKey: clnt.private.PublicKey(), HCSoln: clnt.powork, } kilog.Debug("directory: default provider joining %v", req) err = struc.Pack(sok, &req) if err != nil { return } var iresp srvInitResp err = struc.Unpack(sok, &iresp) if err != nil { return } switch iresp.Code { case "BADP": err = ErrBadPow return case "OKAY": return default: err = errors.New("directory: default provider saw garbage") return } }
func (dpv dftProv) JoinEdge(clnt Client) (toret []Neighbor, err error) { sok := dpv.getSock(clnt) if sok == nil { return nil, errors.New("directory: default provider failed to obtain socket") } defer sok.Close() req := clntRequest{ Code: "EDGE", Address: make([]byte, 4), Port: 0, Secret: clnt.obfsec, PubKey: clnt.private.PublicKey(), HCSoln: clnt.powork, } err = struc.Pack(sok, &req) if err != nil { return } var iresp srvInitResp err = struc.Unpack(sok, &iresp) if err != nil { return } switch iresp.Code { case "BADP": err = ErrBadPow return case "OKAY": var eresp srvEdgeResp err = struc.Unpack(sok, &eresp) if err != nil { return } toret = eresp.Neighs return default: err = errors.New("directory: default provider saw garbage") return } }
// StartForward requests the SAGIRI daemon to forward incoming connections on port `extPort` // to port `intPort`. Returns a string in the form `host:port` that can be used to // connect to the hosted service. The private key must be passed in; it's the caller's // responsibility to keep track of its own private keys. func (dm Daemon) StartForward(privkey natrium.EdDSAPrivate, extPort int, intPort int) (toret string, err error) { conn, err := net.Dial("tcp", "127.0.0.1:12377") if err != nil { return } var greet Daemon err = struc.Unpack(conn, &greet) if err != nil { return } if dm != greet { err = errors.New("something really wrong happened") return } var req ctlCommand req.Verb = ctlCmdHOST req.PrivKey = privkey req.ExtPort = extPort req.IntPort = intPort err = struc.Pack(conn, &req) if err != nil { return } var resp ctlResponse err = struc.Unpack(conn, &resp) if err != nil { return } switch resp.Verb { case ctlRespOKAY: toret = resp.Name return case ctlRespNOPE: err = errors.New(resp.Name) return } pncBadDaemon() return }
func (srv *Server) rqDispatch(sock io.ReadWriteCloser, request clntRequest) { kilog.Debug("directory: incoming client with %v", request.Code) var err error switch request.Code { case "CORE": // We simply queue up a monitor if this is the first time. err = struc.Pack(sock, &srvInitResp{"OKAY"}) if err != nil { kilog.Debug("directory: could not send OKAY to client") return } var ck ChordKey ck.FromBytes(request.PubKey) srv.Lock() defer srv.Unlock() _, ok := srv.key2meta[ck] if !ok { srv.key2meta[ck] = Neighbor{ Address: request.Address, Port: request.Port, Secret: request.Secret, PubKey: request.PubKey, } kilog.Debug("directory: incoming %v", request) go srv.monCore(ck) } // otherwise we have nothing to do case "EDGE": // Now we use a certain terrible hack. // We add the client to the chord, get its neighs, then remove it. srv.Lock() var ck ChordKey var neighs []ChordKey ck.FromBytes(request.PubKey) // actually an edge if !srv.crd.cache[ck] { _, err := srv.crd.Join(ck) if err != nil { kilog.Debug("directory: error while joining chord: %v", err.Error()) srv.Unlock() goto BADF } neighs, err = srv.crd.Neighs(ck) if err != nil { panic(err.Error()) } srv.crd.Leave(ck) } else { // actually already in cord neighs, err = srv.crd.Neighs(ck) if err != nil { panic(err.Error()) } } srv.Unlock() // neighs now has the neighbors err = struc.Pack(sock, &srvInitResp{"OKAY"}) if err != nil { kilog.Debug("directory: could not send OKAY to client") return } realNeighs := make([]Neighbor, len(neighs)) srv.Lock() for i, v := range neighs { lol, ok := srv.key2meta[v] realNeighs[i] = lol if !ok { kilog.Warning("directory: invalid neighbor sent: %x -> %v", ck.ToBytes(), i) } } srv.Unlock() err = struc.Pack(sock, &srvEdgeResp{0, realNeighs}) } /*BADP: err = struc.Pack(sock, &srvInitResp{"BADP"}) if err != nil { kilog.Debug("directory: could not send BADP to client") } return*/ BADF: err = struc.Pack(sock, &srvInitResp{"BADF"}) if err != nil { kilog.Debug("directory: could not send BADF to client") } return /*ACDN: err = struc.Pack(sock, &srvInitResp{"ACDN"}) if err != nil { kilog.Debug("directory: could not send ACDN to client") } return*/ }
func generateIttoMessage(seqNum int) []byte { type ittoMessageOptionsTrade struct { Type byte Timestamp uint32 Side byte OId uint32 Cross uint32 Match uint32 Price uint32 Size uint32 } type ittoMessageOptionDirectory struct { Type byte Timestamp uint32 OId uint32 Symbol [6]byte ExpirationYear byte ExpirationMonth byte ExpirationDay byte StrikePrice uint32 OType byte Source uint8 UnderlyingSymbol [13]byte ClosingType byte Tradable byte MPV byte } type ittoMessageAddOrder struct { Type byte Timestamp uint32 RefNumD uint32 Side byte OId uint32 Price uint32 Size uint32 } errs.Check(seqNum >= 0) var bb bytes.Buffer switch seqNum % 3 { case 0: m := ittoMessageOptionDirectory{ Type: 'R', OId: uint32(seqNum / 3), } errs.CheckE(struc.Pack(&bb, &m)) case 1: m := ittoMessageOptionsTrade{ Type: 'P', OId: uint32(seqNum / 3), } errs.CheckE(struc.Pack(&bb, &m)) case 2: m := ittoMessageAddOrder{ Type: 'A', RefNumD: uint32(seqNum), Side: 'B', OId: uint32(seqNum/9) + 0x10000, Price: uint32(seqNum % 10 * 1000), Size: uint32(seqNum % 10), } errs.CheckE(struc.Pack(&bb, &m)) } return bb.Bytes() }
func handleControl(clnt io.ReadWriteCloser) { defer clnt.Close() greeting := ctlGreeting{0xCACACACA, ctlVersion{0, 0, 0}, socksPort} // 0.0.0 means unnumbered version err := struc.Pack(clnt, &greeting) if err != nil { kilog.Debug("unable to write control greeting: %v", err.Error()) return } var command ctlCommand err = struc.Unpack(clnt, &command) if err != nil { kilog.Debug("unable to read control command: %v", err.Error()) return } var response ctlResponse defer struc.Pack(clnt, &response) // do the actual work switch command.Verb { case ctlCmdNOOP: return case ctlCmdHOST: kilog.Debug("received control request to forward port %v to %v, with %v", command.IntPort, command.ExtPort, command.PrivKey) ctlState.RLock() _, ok := ctlState.prt2prv[command.ExtPort] ctlState.RUnlock() if ok { kilog.Debug("port %v already occupied, refusing request!", command.ExtPort) response.Verb = ctlRespNOPE response.Name = "port already occupied" return } ctlState.Lock() defer ctlState.Unlock() newlistnr, err := kiricom.EasyListen(fmt.Sprintf("0.0.0.0:%v", command.ExtPort), command.PrivKey, command.PrivKey.PublicKey()) kilog.Debug("startControl secret is %x", command.PrivKey.PublicKey()) if err != nil { kilog.Debug("could not create ICOM listener") response.Verb = ctlRespNOPE response.Name = err.Error() return } ctlState.prt2lst[command.ExtPort] = newlistnr ctlState.prt2prv[command.ExtPort] = command.PrivKey response.Verb = ctlRespOKAY pubip, err := getPublicIP() if err != nil { kilog.Critical("computer does not seem to have an Internet connection; dying!") os.Exit(-1) } response.Name = sagiriNames.EdgeID{command.PrivKey.PublicKey(), pubip, uint16(command.ExtPort)}.String() groop, err := newServGroup(command.PrivKey) if err != nil { kilog.Debug("host: could not start servGroup %v", err.Error()) return } // time to spin off threads to forward the connections handle := func(clnt io.ReadWriteCloser) { defer clnt.Close() fwd, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%v", command.IntPort)) if err != nil { kilog.Debug("host: could not forward %v", err.Error()) return } kilog.Debug("host: completed forwarding") defer fwd.Close() go func() { defer fwd.Close() defer clnt.Close() io.Copy(fwd, clnt) }() io.Copy(clnt, fwd) } go func() { defer newlistnr.Close() defer groop.Destroy() for { clnt, err := newlistnr.Accept() if err != nil { kilog.Debug("host: direct error %v", err.Error()) return } go handle(clnt) } }() go func() { defer groop.Destroy() defer newlistnr.Close() REDO: for { clnt, err := groop.Accept() if err != nil { kilog.Debug("host: onion error %v", err.Error()) groop.Destroy() groop, err = newServGroup(command.PrivKey) if err != nil { kilog.Debug(err.Error()) time.Sleep(time.Second) } goto REDO } go handle(clnt) } }() case ctlCmdSTOP: ctlState.Lock() defer ctlState.Unlock() _, ok := ctlState.prt2lst[command.ExtPort] if !ok { response.Verb = ctlRespNOPE response.Name = "no service with the given port" return } rlPriv := ctlState.prt2prv[command.ExtPort] if subtle.ConstantTimeCompare(rlPriv, command.PrivKey) != 1 { response.Verb = ctlRespNOPE response.Name = "given private key incorrect, refusing to remove" return } delete(ctlState.prt2prv, command.ExtPort) ctlState.prt2lst[command.ExtPort].Close() response.Verb = ctlRespOKAY } }
func (self *ChunkMeta) ToBinary() ([]byte, error) { var buf bytes.Buffer err := struc.Pack(&buf, self) return buf.Bytes(), err }