func (nego *d5SNegotiation) verifyThenDHExchange(conn net.Conn, credBuf []byte) (key []byte, err error) {
	userIdentity, err := RSADecrypt(credBuf, nego.RSAKeys.priv)
	ThrowErr(err)
	clientIdentity := string(userIdentity)
	if log.V(2) {
		log.Infoln("Auth clientIdentity:", clientIdentity)
	}
	allow, ex := nego.AuthSys.Authenticate(userIdentity)
	cDHPub, err := ReadFullByLen(2, conn)
	if !allow {
		log.Warningf("Auth %s failed: %v\n", clientIdentity, ex)
		conn.Write([]byte{0, 1, 0xff})
		return nil, ex
	}
	nego.clientIdentity = clientIdentity
	key = takeSharedKey(nego.dhKeys, cDHPub)
	//	if log.V(5) {
	//		dumpHex("Sharedkey", key)
	//	}
	buf := new(bytes.Buffer)
	buf.Write(nego.dhKeys.pubLen)
	buf.Write(nego.dhKeys.pub)
	_, err = buf.WriteTo(conn)
	return
}
func (nego *d5SNegotiation) negotiate(hconn *hashedConn) (session *Session, err error) {
	setSoTimeout(hconn)
	nego.clientAddr = hconn.RemoteAddr().String()
	var (
		nr  int
		buf = make([]byte, DMLEN1)
	)
	nr, err = hconn.Read(buf)
	ThrowErr(err)

	if nr == DMLEN2 {
		if d5SumValid(buf[TKSZ-2], buf[TKSZ]) && d5SumValid(buf[TKSZ-1], buf[TKSZ+1]) {
			return nego.transSession(hconn, buf)
		}
	}
	if nr == DMLEN1 && d5SumValid(buf[0xd5], buf[0xff]) {
		var (
			skey []byte
			cf   *CipherFactory
		)
		skey, err = nego.verifyThenDHExchange(hconn, buf[256:])
		ThrowErr(err)
		cf = NewCipherFactory(nego.Algo, skey)
		hconn.cipher = cf.NewCipher(nil)
		session = NewSession(hconn.Conn, cf, nego.clientIdentity)
		err = nego.respondTestWithToken(hconn, session)
		return
	}
	log.Warningf("Unrecognized Request from=%s len=%d\n", hconn.RemoteAddr(), nr)
	return nil, NEGOTIATION_FAILED
}
func (c *Client) commandHandler(cmd byte, args []byte) {
	switch cmd {
	case TOKEN_REPLY:
		c.putTokens(args)
	default:
		log.Warningf("Unrecognized command=%x packet=[% x]\n", cmd, args)
	}
}
func (t *Session) commandHandler(cmd byte, args []byte) {
	switch cmd {
	case TOKEN_REQUEST:
		tokens := t.svr.sessionMgr.createTokens(t, GENERATE_TOKEN_NUM)
		t.sigTun.postCommand(TOKEN_REPLY, tokens)
	default:
		log.Warningf("Unrecognized command=%x packet=[% x]\n", cmd, args)
	}
}
func (t *Session) onSTDisconnected() {
	tid := t.tun.identifier
	SafeClose(t.tun)
	atomic.AddInt32(&t.svr.stCnt, -1)
	log.Warningf("Client(%s)-ST was disconnected\n", tid)
	i := t.svr.sessionMgr.clearTokens(t)
	if log.V(4) {
		log.Infof("Clear tokens %d of %s\n", i, tid)
	}
}
Пример #6
0
func (t *Session) tokensHandle(args []byte) {
	var cmd = args[0]
	switch cmd {
	case FRAME_ACTION_TOKEN_REQUEST:
		tokens := t.mgr.createTokens(t, GENERATE_TOKEN_NUM)
		tokens[0] = FRAME_ACTION_TOKEN_REPLY
		t.mux.bestSend(tokens, "replyTokens")
	default:
		log.Warningf("Unrecognized command=%x packet=[% x]\n", cmd, args)
	}
}
Пример #7
0
func tunWrite2(tun *Conn, frm *frame) (err error) {
	err = tun.SetWriteDeadline(time.Now().Add(GENERAL_SO_TIMEOUT * 2))
	if err != nil {
		return
	}
	var nr, nw int
	nr = int(frm.length) + FRAME_HEADER_LEN
	nw, err = tun.Write(frm.toNewBuffer())
	if nr != nw || err != nil {
		log.Warningf("Write tun(%s) error(%v) when sending %s\n", tun.sign(), err, frm)
		SafeClose(tun)
		return
	}
	return nil
}
Пример #8
0
func tunWrite1(tun *Conn, buf []byte) (err error) {
	err = tun.SetWriteDeadline(time.Now().Add(GENERAL_SO_TIMEOUT * 2))
	if err != nil {
		return
	}
	var nr, nw int
	nr = len(buf)
	nw, err = tun.Write(buf)
	if nr != nw || err != nil {
		log.Warningf("Write tun(%s) error(%v) when sending buf.len=%d\n", tun.sign(), err, nr)
		SafeClose(tun)
		return
	}
	return nil
}
Пример #9
0
func sendFrame(frm *frame) (werr bool) {
	dst := frm.conn.conn
	if log.V(5) {
		log.Infoln("SEND queue", frm)
	}
	dst.SetWriteDeadline(time.Now().Add(GENERAL_SO_TIMEOUT))
	nw, ew := dst.Write(frm.data)
	if nw == int(frm.length) && ew == nil {
		return
	}
	werr = true
	// an error occured
	log.Warningf("Write edge(%s) error(%v). %s\n", frm.conn.dest, ew, frm)
	return
}
Пример #10
0
func (c *Client) saveTokens(data []byte) {
	var tokens []byte
	switch data[0] {
	case FRAME_ACTION_TOKEN_REQUEST:
		log.Warningf("unexpected token request")
		return
	case FRAME_ACTION_TOKEN_REPLY:
		tokens = data[1:]
	}
	c.lock.Lock()
	defer c.lock.Unlock()
	c.token = append(c.token, tokens...)
	atomic.CompareAndSwapInt32(&c.State, CLT_PENDING, CLT_WORKING)
	c.pendingTK.notifyAll()
	if log.V(3) {
		log.Infof("Recv tokens=%d pool=%d\n", len(tokens)/TKSZ, len(c.token)/TKSZ)
	}
}
func (nego *d5CNegotiation) validateAndGetTokens(sconn *hashedConn, t *tunParams) (err error) {
	buf, err := ReadFullByLen(2, sconn)
	ThrowErr(err)
	tVer := VERSION
	oVer := binary.BigEndian.Uint32(buf)
	if oVer > tVer {
		oVerStr := fmt.Sprintf("%d.%d.%04d", oVer>>24, (oVer>>16)&0xFF, oVer&0xFFFF)
		tVer >>= 16
		oVer >>= 16
		if tVer == oVer {
			log.Warningf("Caution !!! Please upgrade to new version, remote is v%s\n", oVerStr)
		} else {
			return INCOMPATIBLE_VERSION.Apply(oVerStr)
		}
	}
	ofs := 4
	t.stInterval = int(binary.BigEndian.Uint16(buf[ofs:]))
	ofs += 2
	t.dtInterval = int(binary.BigEndian.Uint16(buf[ofs:]))
	ofs += 2
	t.tunQty = int(buf[ofs])
	t.token = buf[TUN_PARAMS_LEN:]
	if log.V(2) {
		n := len(buf) - TUN_PARAMS_LEN
		log.Infof("Got tokens length=%d\n", n/TKSZ)
	}
	rHash := sconn.RHashSum()
	wHash := sconn.WHashSum()
	_, err = sconn.Write(rHash)
	ThrowErr(err)
	oHash := make([]byte, TKSZ)
	_, err = sconn.Read(oHash)
	if !bytes.Equal(wHash, oHash) {
		log.Errorln("Server hash/r is inconsistence with the client/w")
		log.Errorf("rHash: [% x] wHash: [% x]\n", rHash, wHash)
		log.Errorf("oHash: [% x]\n", oHash)
		return INCONSISTENT_HASH
	}
	return
}
Пример #12
0
func (nego *d5SNegotiation) negotiate(hConn *hashedConn) (session *Session, err error) {
	setSoTimeout(hConn)
	nego.clientAddr = hConn.RemoteAddr().String()
	var (
		nr  int
		buf = make([]byte, DMLEN1)
	)
	nr, err = hConn.Read(buf)
	if err != nil {
		return nil, err
	}

	if nr == DMLEN2 &&
		d5SumValid(buf[TKSZ-2], buf[TKSZ]) && d5SumValid(buf[TKSZ-1], buf[TKSZ+1]) {
		return nego.dataSession(hConn, buf)
	}
	if nr == DMLEN1 &&
		d5SumValid(buf[0xd5], buf[0xff]) {
		return nego.handshakeSession(hConn, buf)
	}
	log.Warningf("Unrecognized Request from=%s len=%d\n", nego.clientAddr, nr)
	return nil, NEGOTIATION_FAILED
}