예제 #1
0
파일: proxy.go 프로젝트: berndfo/gortmp
func CheckC2(s1, c2 []byte) (uint32, error) {
	server_pos := rtmp.ValidateDigest(s1, 8, rtmp.GENUINE_FMS_KEY[:36])
	if server_pos == 0 {
		server_pos = rtmp.ValidateDigest(s1, 772, rtmp.GENUINE_FMS_KEY[:36])
		if server_pos == 0 {
			return 0, errors.New("Server response validating failed")
		}
	}

	digest, err := rtmp.HMACsha256(s1[server_pos:server_pos+rtmp.SHA256_DIGEST_LENGTH], rtmp.GENUINE_FP_KEY)
	rtmp.CheckError(err, "Get digest from s1 error")

	signature, err := rtmp.HMACsha256(c2[:rtmp.RTMP_SIG_SIZE-rtmp.SHA256_DIGEST_LENGTH], digest)
	rtmp.CheckError(err, "Get signature from c2 error")

	if bytes.Compare(signature, c2[rtmp.RTMP_SIG_SIZE-rtmp.SHA256_DIGEST_LENGTH:]) != 0 {
		return 0, errors.New("Server signature mismatch")
	}
	return server_pos, nil
}
예제 #2
0
파일: proxy.go 프로젝트: berndfo/gortmp
func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "%s version[%s]\r\nUsage: %s [OPTIONS]\r\n", programName, version, os.Args[0])
		flag.PrintDefaults()
	}
	flag.Parse()

	// listen
	listen, err := net.Listen("tcp", ":1935")
	if err != nil {
		log.Println("Listen error", err)
		os.Exit(-1)
	}
	defer listen.Close()

	for {
		iconn, err := listen.Accept()
		if err != nil {
			log.Println("Accept error", err)
			os.Exit(-1)
		}
		if iconn == nil {
			log.Println("iconn is nil")
			os.Exit(-1)
		}
		defer iconn.Close()
		// Handshake
		// C>>>P: C0+C1
		ibr := bufio.NewReader(iconn)
		ibw := bufio.NewWriter(iconn)
		c0, err := ibr.ReadByte()
		if c0 != 0x03 {
			log.Printf("C>>>P: C0(0x%2x) != 0x03\n", c0)
			os.Exit(-1)
		}
		c1 := make([]byte, rtmp.RTMP_SIG_SIZE)
		_, err = io.ReadAtLeast(ibr, c1, rtmp.RTMP_SIG_SIZE)
		// Check C1
		var clientDigestOffset uint32
		if clientDigestOffset, err = CheckC1(c1, true); err != nil {
			log.Println("C>>>P: Test C1 err:", err)
			os.Exit(-1)
		}
		// P>>>S: Connect Server
		oconn, err := net.Dial("tcp", "192.168.20.111:1935")
		if err != nil {
			log.Println("P>>>S: Dial server err:", err)
			os.Exit(-1)
		}
		defer oconn.Close()
		obr := bufio.NewReader(oconn)
		obw := bufio.NewWriter(oconn)
		// P>>>S: C0+C1
		if err = obw.WriteByte(c0); err != nil {
			log.Println("P>>>S: Write C0 err:", err)
			os.Exit(-1)
		}
		if _, err = obw.Write(c1); err != nil {
			log.Println("P>>>S: Write C1 err:", err)
			os.Exit(-1)
		}
		if err = obw.Flush(); err != nil {
			log.Println("P>>>S: Flush err:", err)
			os.Exit(-1)
		}
		// P<<<S: Read S0+S1+S2
		s0, err := obr.ReadByte()
		if err != nil {
			log.Println("P<<<S: Read S0 err:", err)
			os.Exit(-1)
		}
		if c0 != 0x03 {
			log.Printf("P<<<S: S0(0x%2x) != 0x03\n", s0)
			os.Exit(-1)
		}
		s1 := make([]byte, rtmp.RTMP_SIG_SIZE)
		_, err = io.ReadAtLeast(obr, s1, rtmp.RTMP_SIG_SIZE)
		if err != nil {
			log.Println("P<<<S: Read S1 err:", err)
			os.Exit(-1)
		}
		s2 := make([]byte, rtmp.RTMP_SIG_SIZE)
		_, err = io.ReadAtLeast(obr, s2, rtmp.RTMP_SIG_SIZE)
		if err != nil {
			log.Println("P<<<S: Read S2 err:", err)
			os.Exit(-1)
		}

		// C<<<P: Send S0+S1+S2
		if err = ibw.WriteByte(s0); err != nil {
			log.Println("C<<<P: Write S0 err:", err)
			os.Exit(-1)
		}
		if _, err = ibw.Write(s1); err != nil {
			log.Println("C<<<P: Write S1 err:", err)
			os.Exit(-1)
		}
		if _, err = ibw.Write(s2); err != nil {
			log.Println("C<<<P: Write S2 err:", err)
			os.Exit(-1)
		}
		if err = ibw.Flush(); err != nil {
			log.Println("C<<<P: Flush err:", err)
			os.Exit(-1)
		}

		// C>>>P: Read C2
		c2 := make([]byte, rtmp.RTMP_SIG_SIZE)
		_, err = io.ReadAtLeast(ibr, c2, rtmp.RTMP_SIG_SIZE)

		// Check S2
		server_pos := rtmp.ValidateDigest(s1, 8, rtmp.GENUINE_FP_KEY[:30])
		if server_pos == 0 {
			server_pos = rtmp.ValidateDigest(s1, 772, rtmp.GENUINE_FP_KEY[:30])
			if server_pos == 0 {
				log.Println("P<<<S: S1 position check error")
				os.Exit(-1)
			}
		}

		digest, err := rtmp.HMACsha256(c1[clientDigestOffset:clientDigestOffset+rtmp.SHA256_DIGEST_LENGTH], rtmp.GENUINE_FMS_KEY)
		rtmp.CheckError(err, "Get digest from c1 error")

		signature, err := rtmp.HMACsha256(s2[:rtmp.RTMP_SIG_SIZE-rtmp.SHA256_DIGEST_LENGTH], digest)
		rtmp.CheckError(err, "Get signature from s2 error")

		if bytes.Compare(signature, s2[rtmp.RTMP_SIG_SIZE-rtmp.SHA256_DIGEST_LENGTH:]) != 0 {
			log.Println("Server signature mismatch")
			os.Exit(-1)
		}

		digestResp, err := rtmp.HMACsha256(s1[server_pos:server_pos+rtmp.SHA256_DIGEST_LENGTH], rtmp.GENUINE_FP_KEY)
		rtmp.CheckError(err, "Generate C2 HMACsha256 digestResp")
		signatureResp, err := rtmp.HMACsha256(c2[:rtmp.RTMP_SIG_SIZE-rtmp.SHA256_DIGEST_LENGTH], digestResp)
		if bytes.Compare(signatureResp, c2[rtmp.RTMP_SIG_SIZE-rtmp.SHA256_DIGEST_LENGTH:]) != 0 {
			log.Println("C2 mismatch")
			os.Exit(-1)
		}

		// P>>>S: Send C2
		if _, err = obw.Write(c2); err != nil {
			log.Println("P>>>S: Write C2 err:", err)
			os.Exit(-1)
		}
		if err = obw.Flush(); err != nil {
			log.Println("P>>>S: Flush err:", err)
			os.Exit(-1)
		}

		// Proxy
		go io.Copy(iconn, oconn)
		go io.Copy(oconn, iconn)
	}
}