Beispiel #1
0
func (cc *ClientCtx) thrMain() {
	defer cc.Close()

	// thrMain only handles incoming segments
	for {
		select {
		case <-cc.cmn.deadch:
			return
		case seg := <-cc.cmn.dnch:
			switch seg.Flag {
			case kcOPEN:
				kilog.Warning("kiricom: severe protocol violation: kcOPEN on client")
				return

			case kcDATA:
				fallthrough
			case kcCLOS:
				cc.tablock.Lock()
				tgt, ok := cc.conntab[seg.ConnID]
				cc.tablock.Unlock()
				if !ok {
					kilog.FineDebug("kiricom: %v to invalid connid", seg)
					continue
				}
				select {
				case tgt.inbox <- seg:
				default:
					kilog.Warning("kiricom: severe protocol violation: overfull flow control buffer")
					return
				}
				if seg.Flag == kcCLOS {
					cc.tablock.Lock()
					delete(cc.conntab, seg.ConnID)
					cc.tablock.Unlock()
				}

			case kcMORE:
				cc.tablock.Lock()
				tgt, ok := cc.conntab[seg.ConnID]
				cc.tablock.Unlock()
				if !ok {
					kilog.FineDebug("kiricom: %v to invalid connid", seg)
					continue
				}
				select {
				case tgt.morech <- true:
					kilog.FineDebug("kiricom: sent MORE to connid %v", tgt.connid)
				default:
					kilog.Warning("kiricom: severe protocol violation: duplicate MORE")
					return
				}
			}
		}
	}
}
func run_monitor_loop() {
	onionstew.DownloadIncrement = incr_down_bytes
	onionstew.DownloadOverheadIncrement = incr_down_overhead_bytes
	onionstew.UploadIncrement = incr_up_bytes
	onionstew.UploadOverheadIncrement = incr_up_overhead_bytes

	listener, err := net.Listen("tcp", "127.0.0.1:9221")
	if err != nil {
		panic(err.Error())
	}
	for {
		client, err := listener.Accept()
		if err != nil {
			kilog.Warning(err.Error())
			continue
		}
		func() {
			defer client.Close()
			for {
				thing := <-global_monitor_chan
				_, err := client.Write(thing)
				if err != nil {
					return
				}
			}
		}()
	}
}
Beispiel #3
0
func (sg *servGroup) connAmb(i int) (*kiricom.ServerCtx, error) {
	nonce := make([]byte, 8)
	binary.BigEndian.PutUint64(nonce, uint64(i))
	hash := natrium.SecureHash(sg.aidee.PublicKey(), nonce)

	kilog.Debug("serv: building circuit %v -> %x for %v", i, hash, sg.aidee.PublicKey())
	var tgt directory.ChordKey
	tgt.FromBytes(hash)

	// build circuit to each and every one of them
	thingy, err := buildCirc(tgt)
	if err != nil {
		//thingy.Destroy()
		return nil, err
	}
	haha, err := thingy.RegAmbassador(sg.aidee.PublicKey())
	if err != nil {
		thingy.Destroy()
		if err == core2core.ErrRejectedReq {
			kilog.Warning("serv: circuit number %v for %v rejected", i, sg.aidee.PublicKey())
			return nil, err
		} else {
			return nil, err
		}
	}
	return haha, nil
}
Beispiel #4
0
func tcpLoop() {
	listener, err := net.ListenTCP("tcp", transThis)
	if err != nil {
		kilog.Critical("%v", err.Error())
		os.Exit(-1)
	}
	for {
		clnt, err := listener.AcceptTCP()
		if err != nil {
			kilog.Critical("%v", err.Error())
			os.Exit(-1)
		}
		go func() {
			defer clnt.Close()
			defer clnt.CloseRead()
			defer clnt.CloseWrite()

			lol, err := clnt.File()
			if err != nil {
				panic(err.Error())
			}
			haha := C.getdestaddr_iptables(C.int(lol.Fd()))
			lol.Close()

			sdf := make([]byte, 4)
			binary.LittleEndian.PutUint32(sdf, uint32(haha.sin_addr.s_addr))

			port := binary.BigEndian.Uint16((*[2]byte)(unsafe.Pointer(&haha.sin_port))[:])

			rmAddr := &net.TCPAddr{sdf, int(port), ""}
			dnsLock.Lock()
			rmName, ok := ipToName[rmAddr.IP.String()]
			dnsLock.Unlock()
			var rmConn io.ReadWriteCloser
			// see if we should connect IP or name
			if !ok {
				kilog.Warning("unmapped IP received (%v), misconfig?", rmAddr)
				rmConn, err = socksConnectIP(socksNext, rmAddr)
			} else {
				kilog.Debug("mapped IP received (%v -> %v)", rmAddr, rmName)
				rmConn, err = socksConnectName(socksNext, rmName, rmAddr.Port)
			}
			if err != nil {
				kilog.Debug("%v", err)
				return
			}
			defer rmConn.Close()
			go func() {
				defer rmConn.Close()
				defer clnt.Close()
				defer clnt.CloseRead()
				defer clnt.CloseWrite()
				io.Copy(rmConn, clnt)
			}()
			io.Copy(clnt, rmConn)
			kilog.Debug("closing client")
		}()
	}
}
Beispiel #5
0
func (dpv dftProv) getSock(clnt Client) io.ReadWriteCloser {
	sock, err := net.Dial("tcp", dpv.url)
	if err != nil {
		kilog.Warning("directory: default provider failed: %v", err.Error())
		return nil
	}
	/*obsok, err := kiss.LLObfsClientHandshake(dpv.PublicKey(), sock)
	if err != nil {
		kilog.Warning("directory: default provider failed: %v", err.Error())
		sock.Close()
		return nil
	}*/
	secsok, err := kiss.KiSSNamedHandshake(clnt.private, kiss.NewDirectVerifier(dpv.PublicKey()), sock)
	if err != nil {
		kilog.Warning("directory: default provider failed: %v", err.Error())
		sock.Close()
		return nil
	}
	return secsok
}
Beispiel #6
0
func runCore(id directory.Client) {
	state := core2core.NewNodeState(dirProvider, id)

	addr := id.GetAddress()
	srv, err := kiricom.EasyListen(fmt.Sprintf("0.0.0.0:%v", addr.Port), nil, id.GetSecret())
	if err != nil {
		panic(err.Error())
	}

	err = dirProvider.JoinCore(id)
	if err != nil {
		panic(err.Error())
	}

	go func() {
		for {
			time.Sleep(time.Minute * 5)
			err = dirProvider.JoinCore(id)
			if err != nil {
				kilog.Warning("core: error while joining %v", err.Error())
			}
		}
	}()

	fmt.Println(id.GetAddress())

	kilog.Info("started core service on %v", addr)
	for {
		client, err := srv.Accept()
		if err != nil {
			panic(err.Error())
		}
		kilog.Debug("core: accepted a client")
		go func() {
			err := state.HandleClient(client)
			if err != nil {
				kilog.Warning("core: error %v", err)
			}
		}()
	}
}
Beispiel #7
0
func getNeighs(id directory.Client) {
	var neighs []directory.Neighbor
	for len(neighs) == 0 {
		var err error
		neighs, err = dirProvider.JoinEdge(id)
		if err != nil {
			kilog.Warning("failure in getNeighs(): %v", err)
			time.Sleep(time.Second)
			continue
		}
		fmt.Println(neighs)
	}
	circPool.Lock()
	defer circPool.Unlock()
	circPool.neighs = neighs
}
Beispiel #8
0
func (sg *servGroup) revAmbass(num int) {
retry:
	noo, err := sg.connAmb(num)
	if err != nil {
		kilog.Warning("serv: ambassador %v of %v has problems resurrecting: %v", num, sg.aidee.PublicKey(), err.Error())
		getNeighs(dirClient)
		if err != core2core.ErrRejectedReq {
			time.Sleep(time.Second)
			goto retry
		}
		sg.ambass[num] = nil
	} else {
		sg.ambass[num] = noo
		go sg.runAmbass(num, noo)
	}
}
Beispiel #9
0
func (cg *circGroup) Dial() (io.ReadWriteCloser, error) {
	req := make(chan io.ReadWriteCloser)
	select {
	case <-cg.dedchan:
		return nil, ErrDeadCG
	case cg.inchan <- req:
		select {
		case wire := <-req:
			if wire == nil {
				return nil, ErrDeadCG
			} else {
				return wire, nil
			}
		case <-cg.dedchan:
			return nil, ErrDeadCG
		}
	case <-time.After(time.Second * 5):
		kilog.Warning("circ: bad circuit group")
		cg.Destroy()
		return nil, ErrDeadCG
	}
}
func run_diagnostic_loop() {
	listener, err := net.Listen("tcp", "127.0.0.1:9222")
	if err != nil {
		panic(err)
	}
	for {
		nconn, err := listener.Accept()
		if err != nil {
			kilog.Warning("Problem while accepting stacktrace diag socket: %s", err.Error())
			continue
		}
		go func() {
			defer nconn.Close()
			for {
				str := <-kilog.FineChannel
				_, err := nconn.Write([]byte(fmt.Sprintf("%s\n", str)))
				if err != nil {
					return
				}
			}
		}()
	}
}
Beispiel #11
0
func handleSocks(clnt io.ReadWriteCloser) {
	defer clnt.Close()
	defer kilog.Debug("exited handleSocks")
	destin, err := socks5.ReadRequest(clnt)
	if err != nil {
		kilog.Warning("problem while reading SOCKS5 request: %v", err.Error())
		return
	}
	kilog.Debug("SOCKS beginning to handle %v", destin)
	if !sagiriNames.CheckEdgeID(destin) {
		kilog.Warning("invalid name (%v) sent to SOCKS subsystem, misconfig?", destin)
		// 0x08, address type not supported
		socks5.CompleteRequest(0x08, clnt)
		return
	}
	parsed := sagiriNames.ParseEdgeID(destin)

	if parsed.IPAddress == nil {
		/*kilog.Warning("SOCKS only supports direct connections currently, refusing!")
		// 0x08, address type not supported
		socks5.CompleteRequest(0x08, clnt)
		return*/

		remote, err := dialPubKey(parsed.PubKey)
		if err != nil {
			kilog.Debug("SOCKS failed to connect to remote anon host (%v)", err)
			return
		}
		defer remote.Close()

		err = socks5.CompleteRequest(0x00, clnt)
		if err != nil {
			kilog.Debug("SOCKS failed to send back response (%v)", err)
			return
		}

		// forward between local and remote
		go func() {
			defer clnt.Close()
			defer remote.Close()
			io.Copy(remote, clnt)
		}()
		io.Copy(clnt, remote)
	} else {

		kiriaddr := fmt.Sprintf("%v:%v", parsed.IPAddress, parsed.PortNum)
		secret := parsed.PubKey
		// verifier function
		verifier := func(other natrium.EdDSAPublic) bool {
			return subtle.ConstantTimeCompare(other,
				parsed.PubKey) == 1
		}
		remote, err := kiricom.EasyDial(kiriaddr, verifier, secret)
		if err != nil {
			kilog.Debug("SOCKS failed to connect to remote host (%v)", err)
			// 0x04, host unreachable
			socks5.CompleteRequest(0x04, clnt)
			return
		}
		kilog.Debug("SOCKS succesfully connected to %v:%v on ICOM", parsed.IPAddress,
			parsed.PortNum)
		defer remote.Close()
		err = socks5.CompleteRequest(0x00, clnt)
		if err != nil {
			kilog.Debug("SOCKS failed to send back response (%v)", err)
			return
		}
		kilog.Debug("SOCKS successfully sent back response")
		// forward between local and remote
		go func() {
			defer clnt.Close()
			defer remote.Close()
			io.Copy(remote, clnt)
		}()
		io.Copy(clnt, remote)
	}
}
Beispiel #12
0
func (sc *ServerCtx) thrMain() {
	defer sc.Close()

	for {
		var seg kcSegment
		select {
		case seg = <-sc.cmn.dnch:
			switch seg.Flag {
			case kcOPEN:
				// conn open request
				_, exists := sc.cltab[seg.ConnID]
				if exists {
					kilog.Warning("kiricom: severe protocol violation: OPEN for already open connection")
					return
				}
				// isn't a protocol violation, continue normally
				sok := newKcPayload(sc.limit, sc.cmn.upch)
				sc.cltab[seg.ConnID] = sok
				sok.connid = seg.ConnID
				select {
				case sc.clch <- sok:
					kilog.Debug("kiricom: accepted connid %v", seg.ConnID)
					go func() { // death coupler
						select {
						case <-sok.deadch:
						case <-sc.cmn.deadch:
							sok.destroy("global death")
						}
					}()
				default:
					kilog.Warning("kiricom: accept queue overfull, rejecting connection")
					reset := seg
					reset.Flag = kcCLOS
					go func() { // in new thread to avoid blocking up the queue
						select {
						case sc.cmn.upch <- reset:
						case <-sc.cmn.deadch:
						}
					}()
				}

			case kcDATA:
				fallthrough
			case kcCLOS:
				tgt, ok := sc.cltab[seg.ConnID]
				if !ok {
					kilog.Debug("kiricom: %v to invalid connid", seg)
					continue
				}
				select {
				case tgt.inbox <- seg:
				default:
					kilog.Warning("kiricom: severe protocol violation: overfull flow control buffer")
					return
				}
				if seg.Flag == kcCLOS {
					delete(sc.cltab, seg.ConnID)
				}

			case kcMORE:
				tgt, ok := sc.cltab[seg.ConnID]
				if !ok {
					kilog.Debug("kiricom: %v to invalid connid", seg)
					continue
				}
				select {
				case tgt.morech <- true:
					kilog.Debug("kiricom: sent MORE to connid %v", tgt.connid)
				default:
					kilog.Warning("kiricom: severe protocol violation: duplicate MORE")
					return
				}
			}
		case <-sc.cmn.deadch:
			return
		}
	}
}
Beispiel #13
0
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*/
}
Beispiel #14
0
func newServGroup(aidee natrium.EdDSAPrivate) (*servGroup, error) {
	ambass := make([]*kiricom.ServerCtx, 8)
	toret := new(servGroup)
	toret.ambass = ambass
	toret.deadch = make(chan bool)
	toret.wirech = make(chan io.ReadWriteCloser)
	toret.once = new(sync.Once)
	toret.aidee = aidee

	// contact all the ambassadors
	for i := 0; i < 8; i++ {
		haha, err := toret.connAmb(i)
		if err != nil && err != core2core.ErrRejectedReq {
			for j := 0; j < i; j++ {
				if ambass[j] != nil {
					ambass[j].Close()
				}
			}
			return nil, err
		}
		ambass[i] = haha
	}
	kilog.Debug("serv: all ambassadors of %v notified", aidee.PublicKey())

	// spin off a thread to update ambassadors from time to time
	go func() {
		for {
			time.Sleep(time.Minute * 20)
		FAST:
			time.Sleep(time.Second)
			allbad := true
			for _, v := range ambass {
				if v != nil {
					allbad = false
					break
				}
			}

			if allbad {
				kilog.Warning("serv: ambassadors ALL BAD!")
				for i := 0; i < 8; i++ {
					toret.revAmbass(i)
				}
				continue
			}

			// pick a random ambassador, kill, and resurrect
			// TODO do something more graceful here
			num := rand.Int() % len(ambass)
			kilog.Debug("serv: ambassador %v of %v condemned", num, aidee.PublicKey())
			condemned := ambass[num]
			if condemned != nil {
				kilog.Debug("serv: actually executed condemnation")
				condemned.Close()
			} else {
				goto FAST
			}
		}
	}()

	// spin up threads to handle incoming connections
	for i, lol := range ambass {
		lol := lol
		i := i
		if lol != nil {
			go toret.runAmbass(i, lol)
		}
	}
	// return
	return toret, nil
}
func (ctx *sc_ctx) AttachSC(wire io.ReadWriteCloser, serverside bool) {
	kilog.Debug("AttachSC(%v)", serverside)
	ctx.lock.Lock()
	ctx.refcount++
	ctx.lock.Unlock()
	defer func() {
		ctx.lock.Lock()
		ctx.refcount--
		ctx.lock.Unlock()
	}()
	local_stop := make(chan bool)  // Signal once for close, synchronous
	local_close := make(chan bool) // Close to remove this sc from the premises, cleanly
	ctx.close_ch_ch <- local_close
	// Read from the other side
	go func() {
		id := rand.Int()
		for {
			newpkt, err := read_sc_message(wire)
			if err != nil {
				kilog.Warning("AttachSC encountered unexpected error %s on %x while READING, DESTROYING STEW",
					err.Error(), id)
				ctx.destroy()
				wire.Close()
				return
			}
			// Check for the dead seqnum
			if newpkt.seqnum == 0xFFFFFFFFFFFFFFFF {
				kilog.Debug("Close message received from remote in AttachSC on %x, signalling...", id)
				if serverside {
					local_stop <- true
					kilog.Debug("Close signal successful, sending bakk and returning from %x.", id)
					clmsg := sc_message{0xFFFFFFFFFFFFFFFF, []byte("")}
					write_sc_message(clmsg, wire)
					time.Sleep(time.Second * 10)
					wire.Close()
				} else {
					wire.Close()
				}
				return
			}
			// Check for ignorable message
			if newpkt.seqnum == 0xFFFFFFFFFFFFFFFE {
				DownloadOverheadIncrement(len(newpkt.payload))
				continue
			}
			select {
			case ctx.unordered_ch <- newpkt:
				DownloadIncrement(len(newpkt.payload))
			case <-ctx.killswitch:
				kilog.Debug("Great, we got a KILLSWITCH instead of being able to put into unordered, fml")
				wire.Close()
				return
			}
		}
	}()
	// Write to the other side
	for {
		select {
		case newthing := <-ctx.write_ch:
			err := write_sc_message(newthing, wire)
			if err != nil {
				kilog.Warning("AttachSC encountered unexpected error %s while WRITING, DESTROYING STEW",
					err.Error())
				ctx.destroy()
				// Will die on next iteration
			}
			UploadIncrement(len(newthing.payload))
		case <-local_stop:
			return
		case <-local_close:
			kilog.Debug("AttachSC receiving LOCAL_CLOSE, stopping flow & sending remote")
			clmsg := sc_message{0xFFFFFFFFFFFFFFFF, []byte("")}
			write_sc_message(clmsg, wire)
			return
		case <-ctx.killswitch:
			kilog.Debug("AttachSC receiving KILLSWITCH, destroying wire")
			wire.Close()
			return
		}
	}
}
func main() {
	rand.Seed(time.Now().UnixNano())
	go run_monitor_loop()
	flag.Parse()
	if *confloc == "" {
		kilog.Warning("No configuration file given, using defaults")
	} else {
		err := gcfg.ReadFileInto(&MasterConfig, *confloc)
		if err != nil {
			kilog.Warning("Configuration file broken, using defaults")
		}
	}
	if *singhop {
		MasterConfig.Network.MinCircuitLen = 1
	}
	kilog.Info("Kirisurf %s started! mkh=%s", version, MasterKeyHash)
	set_gui_progress(0.1)
	kilog.Info("Bootstrapping 10%%: finding directory address...")
	dirclient.DIRADDR, _ = dirclient.FindDirectoryURL()
	set_gui_progress(0.2)
	kilog.Info("Bootstrapping 20%%: found directory address, refreshing directory...")
	err := dirclient.RefreshDirectory()
	if err != nil {
		kilog.Critical("Stuck at 20%%: directory connection error %s", err.Error())
		for {
			time.Sleep(time.Second)
		}
	}
	set_gui_progress(0.3)
	kilog.Info("Bootstrapping 30%%: directory refreshed, beginning to build circuits...")
	go run_diagnostic_loop()
	dirclient.RefreshDirectory()
	if MasterConfig.General.Role == "server" {
		NewSCServer(MasterConfig.General.ORAddr)
		addr := RegisterNGSCServer(MasterConfig.General.ORAddr)
		prt, _ := strconv.Atoi(
			strings.Split(MasterConfig.General.ORAddr, ":")[1])
		go func() {
			err := UPnPForwardAddr(MasterConfig.General.ORAddr)
			err = UPnPForwardAddr(addr)
			if err != nil {
				kilog.Warning("UPnP failed: %s", err)
				if MasterConfig.Network.OverrideUPnP {
					go dirclient.RunRelay(prt, MasterKeyHash,
						MasterConfig.General.IsExit)
				}
				return
			}
			kilog.Info("UPnP successfully forwarded port")
			go dirclient.RunRelay(prt, MasterKeyHash,
				MasterConfig.General.IsExit)
		}()
		kilog.Info("Started server!")
		if *noclient {
			for {
				time.Sleep(time.Second)
			}
		}
	}
	run_client_loop()
	kilog.Info("Kirisurf exited")
}
Beispiel #17
0
func buildCirc(tgt directory.ChordKey) (*core2core.Client, error) {
	// find the closest neighbor to the destination
	circPool.Lock()
	nxt := circPool.neighs[0]
	for _, v := range circPool.neighs[1:] {
		var vkee directory.ChordKey
		var xkee directory.ChordKey
		vkee.FromBytes(v.PubKey)
		xkee.FromBytes(nxt.PubKey)
		if vkee.Distance(tgt).Cmp(xkee.Distance(tgt)) == -1 {
			nxt = v
		}
	}
	circPool.Unlock()
	kilog.Debug("circ: closest neighbor to %x is %v", tgt.ToBytes(), nxt.PubKey)

	// begin to route
	spider, err := core2core.NewClient(nxt)
	if err != nil {
		return nil, err
	}
	//defer spider.Destroy()

	// loop
	closest := false
	for !closest {
		neighs, err := spider.ListNeighs()
		if err != nil {
			spider.Destroy()
			return nil, err
		}
		if len(neighs) == 0 {
			kilog.Warning("circ: topology anomaly! node with no neighbors!")
			spider.Destroy()
			return nil, err
		}
		better := spider.CurrentPublic()
		closest = true
		// can we find a closer one?
		for _, cand := range neighs {
			var candkee directory.ChordKey
			var currkee directory.ChordKey
			candkee.FromBytes(cand)
			currkee.FromBytes(better)
			if candkee.Distance(tgt).Cmp(currkee.Distance(tgt)) == -1 {
				better = cand
				closest = false
			}
		}
		// connect to the next hop
		if !closest {
			kilog.Debug("circ: circuit to %x extending to %v", tgt.ToBytes(), better)
			err = spider.ConnectNext(better)
			if err != nil {
				spider.Destroy()
				return nil, err
			}
		}
	}
	return spider, nil
}
func RunManagedStewServer() string {
	listener, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		panic(err.Error())
	}

	// Keep trakk of shteewz
	type stid struct {
		top uint64
		bot uint64
	}
	stew_table := make(map[stid]*stew_ctx)
	var stew_table_lk sync.Mutex
	kilog.Debug("before gc goroutine")
	// Garbage collect stew table every 30 seconds
	go func() {
		for {
			time.Sleep(time.Second * 30)
			stew_table_lk.Lock()
			for stid, ctx := range stew_table {
				ctx.llctx.lock.Lock()
				cnt := ctx.llctx.refcount
				ctx.llctx.lock.Unlock()
				if cnt == 0 {
					ctx.destroy()
					stid := stid
					go func() {
						stew_table_lk.Lock()
						kilog.Debug("Collecting %d:%d...", stid.top, stid.bot)
						delete(stew_table, stid)
						stew_table_lk.Unlock()
					}()
				}
			}
			stew_table_lk.Unlock()
		}
	}()
	kilog.Debug("before main goroutine")
	go func() {
		for {
			thing, err := listener.Accept()
			if err != nil {
				continue
			}
			go func() {
				// Obtain the stew id
				idbuf := make([]byte, 16)
				_, err := io.ReadFull(thing, idbuf)
				if err != nil {
					thing.Close()
					kilog.Warning("Client didn't send the entire stew ID before dying")
					return
				}
				kilog.Debug("Obtained new SC on server with id=%x", idbuf)
				top := binary.BigEndian.Uint64(idbuf[0:8])
				bot := binary.BigEndian.Uint64(idbuf[8:16])
				id := stid{top, bot}
				stew_table_lk.Lock()
				if stew_table[id] == nil {
					stew_table[id] = make_stew_ctx()
					go stew_table[id].run_stew(true)
				}
				xaxa := stew_table[id]
				stew_table_lk.Unlock()
				xaxa.llctx.AttachSC(thing, true)
			}()
		}
	}()
	kilog.Debug("before return")
	return listener.Addr().String()
}
func findPath(directory []KNode, minlen int, condition func(KNode) bool) []KNode {
	if minlen > len(directory) {
		minlen = len(directory)
	}

	kilog.Debug("Building a circuit with minimum length %d", minlen)

	rand256 := func() int {
		buf := make([]byte, 1)
		rand.Read(buf)
		return int(buf[0])
	}

	if len(directory) < minlen {
		minlen = len(directory)
		if minlen == 0 {
			kilog.Warning("No nodes online, cannot build any circuit!!!!")
			return nil
		}
	}
	toret := make([]KNode, 0)
	// Find an entry point
	var entry KNode
	for {
		idx := rand256() % len(directory)
		thing := directory[idx]
		if thing.Address != "(hidden)" && rand256()%10 < 1 {
			entry = thing
			break
		}
	}
	// Push the entry onto the slice
	toret = append(toret, entry)
	//history := make(map[int]bool)
	endptr := 0
	for {
		adj := toret[endptr].Adjacents
		// If already at the end, return
		if endptr+1 >= minlen && condition(toret[endptr]) {
			// We want to almost always prune away paths that are ludicrously long,
			// but we can use them if no other choice
			if endptr-minlen < 3 && endptr/minlen <= 2 || rand256() < 3 {
				return toret
			} else {
				return findPath(directory, minlen, condition)
			}
		}
		// Otherwise chug along
	xaxa:
		idx := rand256() % len(adj)
		next := directory[adj[idx]]
		// We cannot allow loops in the path, unless we have to
		for _, ele := range toret {
			if ele.PublicKey == next.PublicKey && rand256() < 250 {
				goto xaxa
			}
		}
		toret = append(toret, next)
		endptr++
		// Absolutely ridiculous paths
		if len(toret) > 1000 {
			kilog.Warning("Didn't find a valid path at all!")
			return nil
		}
	}
	panic("Shouldn't get here")
}
func RunMultiplexServer(transport io.ReadWriteCloser) {
	ctx := make_icom_ctx(transport, true, false, 128)
	for {
		thing, err := ctx.our_srv.Accept()
		if err != nil {
			return
		}
		go func() {
			defer thing.Close()
			init_done := make(chan bool)
			go func() {
				select {
				case <-init_done:
					kilog.Debug("ICOM: Initialization done")
					return
				case <-time.After(time.Second * 10):
					kilog.Warning("ICOM: ** Client still no request after 10 secs **")
				}
			}()
			lenbts := make([]byte, 2)
			_, err := io.ReadFull(thing, lenbts)
			if err != nil {
				kilog.Debug("** Reading destination length failed! **")
				return
			}
			addr := make([]byte, int(lenbts[0])+int(lenbts[1])*256)
			_, err = io.ReadFull(thing, addr)
			if err != nil {
				kilog.Debug("** Reading destination failed! **")
				return
			}
			init_done <- true
			if addr[0] == 't' {
				addr = addr[1:]
			} else {
				kilog.Warning("UDP support not implemented yet!")
				thing.Write([]byte("NOIM"))
				return
			}

			remote, err := net.DialTimeout("tcp", string(addr), time.Second*20)
			if err != nil {
				kilog.Debug("Connection to %s failed: %s", addr, err.Error())
				e := err.(net.Error)
				if e.Timeout() {
					thing.Write([]byte("TMOT"))
				} else {
					thing.Write([]byte("FAIL"))
				}
				return
			}
			defer remote.Close()
			rlrem := remote
			go func() {
				defer rlrem.Close()
				io.Copy(rlrem, thing)
			}()
			kilog.Debug("Opened connection to %s", addr)
			thing.Write([]byte("OKAY"))
			io.Copy(thing, rlrem)
		}()
	}
}
func run_client_loop() {
	listener, err := net.Listen("tcp", MasterConfig.General.SocksAddr)
	if err != nil {
		panic(err)
	}
	circ_ch <- produce_circ()
	set_gui_progress(1.0)
	kilog.Info("Bootstrapping 100%%: client started!")

	go func() {
		var haha sync.WaitGroup
		haha.Add(5)
		for i := 0; i < 5; i++ {
			go func() {
				circ_ch <- produce_circ()
				haha.Done()
			}()
		}
		haha.Wait()
	}()
	for {
		nconn, err := listener.Accept()
		if err != nil {
			kilog.Warning("Problem while accepting client socket: %s", err.Error())
			continue
		}
		go func() {
			defer func() {
				nconn.Close()
			}()
			addr, err := socks5.ReadRequest(nconn)
			if err != nil {
				kilog.Warning("Problem while reading SOCKS5 request")
				return
			}
			kilog.Debug("Attempting connection to %s...", addr)
		retry:
			newcirc := <-circ_ch
			remote, err := newcirc.SocksAccept(nconn)
			if err != nil {
				dirclient.RefreshDirectory()
				circ_ch <- produce_circ()
				goto retry
			}
			circ_ch <- newcirc
			defer remote.Close()
			lenbts := []byte{byte((len(addr) + 1) % 256), byte((len(addr) + 1) / 256)}
			_, err = remote.Write(lenbts)
			_, err = remote.Write([]byte(fmt.Sprintf("t%s", addr)))
			if err != nil {
				kilog.Debug("Failed to send tunnelling request to %s!", addr)
				socks5.CompleteRequest(0x03, nconn)
				return
			}

			kilog.Debug("Sent tunneling request")

			code := make([]byte, 4)
			_, err = io.ReadFull(remote, code)
			if err != nil {
				kilog.Debug("Failed to read response for %s! (%s)", addr, err)
				socks5.CompleteRequest(0x03, nconn)
				return
			}

			switch string(code) {
			case "OKAY":
				kilog.Debug("Successfully tunneled %s!", addr)
				socks5.CompleteRequest(0x00, nconn)
				go func() {
					defer remote.Close()
					io.Copy(remote, nconn)
				}()
				io.Copy(nconn, remote)
			case "TMOT":
				kilog.Debug("Tunnel to %s timed out!", addr)
				socks5.CompleteRequest(0x06, nconn)
			case "NOIM":
				kilog.Debug("Tunnel type for %s isn't implemented by server!", addr)
				socks5.CompleteRequest(0x07, nconn)
			case "FAIL":
				kilog.Debug("Tunnel to %s cannot be established!", addr)
				socks5.CompleteRequest(0x04, nconn)
			default:
				kilog.Debug("Protocol error on tunnel to %s! (%s)", addr, string(code))
				socks5.CompleteRequest(0x01, nconn)
				return
			}
		}()
	}
}
Beispiel #22
0
func newCircGroup(dest natrium.EdDSAPublic) (*circGroup, error) {
	// 8 targets in total
	targets := make([]directory.ChordKey, 8)
	for i := 0; i < 8; i++ {
		nonce := make([]byte, 8)
		binary.BigEndian.PutUint64(nonce, uint64(i))
		hash := natrium.SecureHash(dest, nonce)
		targets[i].FromBytes(hash)
	}

	toret := new(circGroup)
	toret.inchan = make(chan chan io.ReadWriteCloser)
	toret.dedchan = make(chan bool)

	okaych := make(chan bool, 10)

	// spin off goroutines
	for i, tgt := range targets {
		tgt := tgt
		i := i
		kilog.Debug("circ: building circuit %v -> %x for %v", i, tgt.ToBytes(), dest)
		go func() {
			goto SKIP

			// error
		DIE_IN_DISGRACE:
			kilog.Warning("circ: circuit action %v for %v (%x) is aborted!", i, dest, tgt.ToBytes())
			// TODO don't die when just one circuit dies
			//toret.Destroy()
			return
		SKIP:

			spider, err := buildCirc(tgt)
			if err != nil {
				toret.Destroy()
				goto DIE_IN_DISGRACE
			}

			kilog.Debug("circ: circuit to the closest node to %x (%v) established",
				tgt.ToBytes(), spider.CurrentPublic())
			kilog.Debug("circ: patching through ambassador %v to %v...", i, dest)
			thing, err := spider.ConnAmbassador(dest)
			if err != nil {
				spider.Destroy()
				goto DIE_IN_DISGRACE
			}
			kilog.Debug("circ: patched through ambassador to %v! circuit length %v", dest, spider.CircLength())
			defer thing.Close()
			/*if spider.CircLength() < 1 {
				kilog.Debug("circ: aborting %v due to bad length", i)
				return
			}*/
			okaych <- true
			for {
				select {
				case req := <-toret.inchan:
					kilog.Debug("circ: request to %v routed through %v", dest, i)
					wire, err := thing.Dial()
					if err != nil {
						kilog.Warning("circ: request to %v through %v encountered unusable dialer!", dest, i)
						go func() {
							select {
							case toret.inchan <- req:
							case <-time.After(time.Second * 2):
								close(req)
							}
						}()
						return
					}
					go func() {
						select {
						case req <- wire:
						case <-toret.dedchan:
							kilog.Debug("circ: circuit %v for %v closing down safely", i, dest)
						}
					}()
				case <-toret.dedchan:
					kilog.Debug("circ: circuit %v for %v closing down safely", i, dest)
					return
				}
			}

		}()
	}
	select {
	case <-okaych:
	case <-time.After(time.Second * 20):
		kilog.Warning("circ: nothing happened in 20 seconds for %v, dying", dest)
		toret.Destroy()
		return nil, io.ErrNoProgress
	}
	// return
	return toret, nil
}