Beispiel #1
0
func TestServerTestAccount(t *testing.T) {
	A := AccountInfo{
		AccountName: "test account",
		AccessKey:   core.DeepHmac(20000, append([]byte("test account"), []byte("*ACCESS*KEY*PAD*")...), core.Hash([]byte("password"))),
		Datasets:    core.DatasetArray{},
	}
	accountHandler.SetInfo(A)
	JA, _ := json.Marshal(A)

	B := accountHandler.GetInfo(core.Hash([]byte(A.AccountName)))
	JB, _ := json.Marshal(*B)

	if B == nil {
		t.Error("Account not found")
	} else if string(JA) != string(JB) {
		fmt.Println(string(JA))
		fmt.Println(string(JB))
		t.Error("Accounts not equal")
	}

	C := accountHandler.GetInfo(core.Hash([]byte("")))
	if C != nil {
		t.Error("Account without name found")
	}
}
Beispiel #2
0
func TestClientServerAuthentication(t *testing.T) {
	var err error

	conn, err := net.Dial("tcp", "127.0.0.1:1248")
	if err != nil {
		panic(err)
	}

	conn.SetDeadline(time.Now().Add(15 * time.Second))
	client := core.NewClient(conn, "test account", core.DeepHmac(20000, append([]byte("test account"), []byte("*ACCESS*KEY*PAD*")...), core.Hash([]byte("password"))))
	defer client.Close(true)
}
Beispiel #3
0
func TestClientServerHashboxBlocks(t *testing.T) {
	var err error

	conn, err := net.Dial("tcp", "127.0.0.1:1248")
	if err != nil {
		panic(err)
	}

	conn.SetDeadline(time.Now().Add(10 * time.Minute))
	client := core.NewClient(conn, "test account", core.DeepHmac(20000, append([]byte("test account"), []byte("*ACCESS*KEY*PAD*")...), core.Hash([]byte("password"))))
	defer client.Close(true)

	{
		var data bytearray.ByteArray
		data.Write([]byte("HELLO!"))
		blockID := client.StoreData(core.BlockDataTypeRaw, data, nil)
		client.Commit()
		block := client.ReadBlock(blockID)
		if !reflect.DeepEqual(blockID, block.BlockID) {
			t.Error("Received block has wrong ID")
		}

		rdata, _ := block.Data.ReadSlice()
		if !bytes.Equal(rdata, []byte("HELLO!")) {
			t.Error("Block contains wrong data, expected \"HELLO!\" received \"" + string(rdata) + "\"")
		}
	}

	{
		var data bytearray.ByteArray
		data.Write([]byte("Bet it all on black?"))
		blockID := client.StoreData(core.BlockDataTypeRaw, data, nil)
		client.Commit()
		block := client.ReadBlock(blockID)
		if !reflect.DeepEqual(blockID, block.BlockID) {
			t.Error("Received block has wrong ID")
		}
		rdata, _ := block.Data.ReadSlice()
		if !bytes.Equal(rdata, []byte("Bet it all on black?")) {
			t.Error("Block contains wrong data, expected \"Bet it all on black?\" received \"" + string(rdata) + "\"")
		}
	}
}
Beispiel #4
0
func GenerateBackupKey(account string, password string) core.Byte128 {
	return core.DeepHmac(20000, append([]byte(account), []byte("*ENCRYPTION*PAD*")...), core.Hash([]byte(password)))
}
Beispiel #5
0
func GenerateAccessKey(account string, password string) core.Byte128 {
	return core.DeepHmac(20000, append([]byte(account), []byte("*ACCESS*KEY*PAD*")...), core.Hash([]byte(password)))
}
Beispiel #6
0
func handleConnection(conn net.Conn) {
	remoteID := conn.RemoteAddr().String()
	core.Log(core.LogInfo, "%s - Connection established", remoteID)

	defer func() {
		if err := recover(); err != nil {
			core.Log(core.LogError, "%s - %v", remoteID, err)
		}

		core.Log(core.LogInfo, "%s - Connection closed", remoteID)
		conn.Close()
	}()

	var clientSession core.Session
	var sessionAuthenticated = false

	for keepAlive := true; keepAlive; {
		conn.SetReadDeadline(time.Now().Add(10 * time.Minute)) // max size 512kb over 10 minutes is slower than 9600bps so we should be safe
		// TODO: testing non-idle of 10s between commands

		unauthorized := false

		func() {
			incoming := core.ReadMessage(conn)
			defer incoming.Release()
			core.Log(core.LogInfo, "%s < %s %s", remoteID, incoming.String(), incoming.Details())
			reply := &core.ProtocolMessage{Num: incoming.Num, Type: incoming.Type & core.MsgTypeServerMask}
			defer reply.Release()

			switch incoming.Type {
			case core.MsgTypeOldGreeting:
				reply.Type = core.MsgTypeError & core.MsgTypeServerMask
				reply.Data = &core.MsgServerError{"Client uses an outdated protocol version"}
			case core.MsgTypeGreeting:
				c := incoming.Data.(*core.MsgClientGreeting)
				if c.Version < core.ProtocolVersion {
					reply.Type = core.MsgTypeError & core.MsgTypeServerMask
					reply.Data = &core.MsgServerError{"Client uses an outdated protocol version"}
				} else if c.Version > core.ProtocolVersion {
					reply.Type = core.MsgTypeError & core.MsgTypeServerMask
					reply.Data = &core.MsgServerError{"Server uses an outdated protocol version"}
				} else {
					// Create server nonce using  64-bit time and 64-bit random
					binary.BigEndian.PutUint64(clientSession.SessionNonce[0:], uint64(time.Now().UnixNano()))
					binary.BigEndian.PutUint32(clientSession.SessionNonce[8:], rand.Uint32())
					binary.BigEndian.PutUint32(clientSession.SessionNonce[12:], rand.Uint32())
					reply.Data = &core.MsgServerGreeting{clientSession.SessionNonce}
				}
			case core.MsgTypeAuthenticate:
				c := incoming.Data.(*core.MsgClientAuthenticate)
				clientSession.AccountNameH = c.AccountNameH
				account := accountHandler.GetInfo(clientSession.AccountNameH)
				if account != nil {
					clientSession.GenerateSessionKey(account.AccessKey)
					myAuthenticationH := core.DeepHmac(1, c.AccountNameH[:], clientSession.SessionKey)
					sessionAuthenticated = bytes.Equal(myAuthenticationH[:], c.AuthenticationH[:])
				}
				unauthorized = !sessionAuthenticated
			case core.MsgTypeGoodbye:
				keepAlive = false
			default:
				unauthorized = !sessionAuthenticated
				if !unauthorized {
					switch incoming.Type {
					case core.MsgTypeAddDatasetState:
						c := incoming.Data.(*core.MsgClientAddDatasetState)
						unauthorized = c.AccountNameH != clientSession.AccountNameH // TODO: admin support for other accounts hashes?
						if !unauthorized {
							if !storageHandler.doesBlockExist(c.State.BlockID) {
								reply.Type = core.MsgTypeError & core.MsgTypeServerMask
								reply.Data = &core.MsgServerError{"Dataset pointing to a non existent block"}
							} else {
								accountHandler.AddDatasetState(c.AccountNameH, c.DatasetName, c.State)
								// No need to set any data in reply
							}
						}
					case core.MsgTypeRemoveDatasetState:
						c := incoming.Data.(*core.MsgClientRemoveDatasetState)
						unauthorized = c.AccountNameH != clientSession.AccountNameH // TODO: admin support for other accounts hashes?
						if !unauthorized {
							accountHandler.RemoveDatasetState(c.AccountNameH, c.DatasetName, c.StateID)
							// No need to set any data in reply
						}
					case core.MsgTypeListDataset:
						c := incoming.Data.(*core.MsgClientListDataset)
						unauthorized = c.AccountNameH != clientSession.AccountNameH // TODO: admin support for other accounts hashes?
						if !unauthorized {
							list := accountHandler.ListDataset(c.AccountNameH, c.DatasetName)
							if list == nil {
								list = new(dbStateCollection)
							}
							reply.Data = &core.MsgServerListDataset{States: list.States, ListH: list.ListH}
							//				} else {
							//					reply.Type = core.MsgTypeError & core.MsgTypeServerMask
							//					reply.Data = &core.MsgServerError{"Cannot list dataset named " + c.DatasetName}

						}
					case core.MsgTypeAccountInfo:
						c := incoming.Data.(*core.MsgClientAccountInfo)
						unauthorized = c.AccountNameH != clientSession.AccountNameH // TODO: admin support for other accounts hashes?
						if !unauthorized {
							account := accountHandler.GetInfo(c.AccountNameH)
							if account != nil {
								reply.Data = &core.MsgServerAccountInfo{DatasetList: account.Datasets}
							} else {
								reply.Type = core.MsgTypeError & core.MsgTypeServerMask
								reply.Data = &core.MsgServerError{"Cannot find account information"}
							}
						}
					case core.MsgTypeAllocateBlock:
						c := incoming.Data.(*core.MsgClientAllocateBlock)
						if storageHandler.doesBlockExist(c.BlockID) {
							reply.Type = core.MsgTypeAcknowledgeBlock & core.MsgTypeServerMask
							reply.Data = &core.MsgServerAcknowledgeBlock{BlockID: c.BlockID}
						} else {
							reply.Type = core.MsgTypeReadBlock & core.MsgTypeServerMask
							reply.Data = &core.MsgServerReadBlock{BlockID: c.BlockID}
						}
					case core.MsgTypeReadBlock:
						c := incoming.Data.(*core.MsgClientReadBlock)
						block := storageHandler.readBlock(c.BlockID)
						if block == nil {
							reply.Type = core.MsgTypeError & core.MsgTypeServerMask
							reply.Data = &core.MsgServerError{"Invalid blockID"}
							keepAlive = false
						} else {
							reply.Type = core.MsgTypeWriteBlock & core.MsgTypeServerMask
							reply.Data = &core.MsgServerWriteBlock{Block: block}
						}
					case core.MsgTypeWriteBlock:
						c := incoming.Data.(*core.MsgClientWriteBlock)
						if c.Block.VerifyBlock() {
							for _, l := range c.Block.Links {
								if !storageHandler.doesBlockExist(l) {
									reply.Type = core.MsgTypeError & core.MsgTypeServerMask
									reply.Data = &core.MsgServerError{"Linked to non existant block"}
									break
								}
							}
							if !storageHandler.checkFree(int64(c.Block.Data.Len())) {
								reply.Type = core.MsgTypeError & core.MsgTypeServerMask
								reply.Data = &core.MsgServerError{"Write permission is denied because the server is out of space"}
							}
							if reply.Data == nil {
								storageHandler.writeBlock(c.Block)
								reply.Type = core.MsgTypeAcknowledgeBlock & core.MsgTypeServerMask
								reply.Data = &core.MsgServerAcknowledgeBlock{BlockID: c.Block.BlockID}
							}
						} else {
							reply.Type = core.MsgTypeError & core.MsgTypeServerMask
							reply.Data = &core.MsgServerError{"Unable to verify blockID"}
						}
					default:
						panic(errors.New("ASSERT: Well if we reach this point, we have not implemented everything correctly (missing " + incoming.String() + ")"))
					}
				}
			}

			if unauthorized {
				// Invalid authentication
				// TODO: Add to server auth.log
				reply.Type = core.MsgTypeError & core.MsgTypeServerMask
				reply.Data = &core.MsgServerError{"Invalid authentication"}
				keepAlive = false
			}
			core.Log(core.LogInfo, "%s > %s %s", remoteID, reply.String(), reply.Details())
			core.WriteMessage(conn, reply)
		}()
	}
}
Beispiel #7
0
func TestClientServerDataset(t *testing.T) {
	var err error

	conn, err := net.Dial("tcp", "127.0.0.1:1248")
	if err != nil {
		panic(err)
	}

	conn.SetDeadline(time.Now().Add(10 * time.Minute))
	client := core.NewClient(conn, "test account", core.DeepHmac(20000, append([]byte("test account"), []byte("*ACCESS*KEY*PAD*")...), core.Hash([]byte("password"))))
	defer client.Close(true)

	// First make sure there is some data to reference
	var data bytearray.ByteArray
	block := core.NewHashboxBlock(core.BlockDataTypeZlib, data, nil)
	var blockID core.Byte128
	blockID = client.StoreBlock(block)
	client.Commit()

	var array core.DatasetStateArray
	var stateID core.Byte128 // randomByte128()

	copy(stateID[:], []byte("testC"))
	keepstate := core.DatasetState{StateID: stateID, BlockID: blockID, Size: 5, UniqueSize: 42}

	client.AddDatasetState("testset", keepstate)
	array = append(array, core.DatasetStateEntry{State: keepstate})
	copy(stateID[:], []byte("testD"))
	keepstate = core.DatasetState{StateID: stateID, BlockID: blockID, Size: 125, UniqueSize: 33342}
	client.AddDatasetState("testset", keepstate)
	array = append(array, core.DatasetStateEntry{State: keepstate})

	copy(stateID[:], []byte("testA"))
	client.AddDatasetState("testset", core.DatasetState{StateID: stateID, BlockID: blockID, Size: 5, UniqueSize: 42})
	copy(stateID[:], []byte("testB"))
	client.AddDatasetState("testset", core.DatasetState{StateID: stateID, BlockID: blockID, Size: 5, UniqueSize: 42})
	copy(stateID[:], []byte("testB"))
	client.RemoveDatasetState("testset", stateID)
	copy(stateID[:], []byte("testA"))
	client.RemoveDatasetState("testset", stateID)
	client.RemoveDatasetState("testset", stateID)

	hash := md5.New()
	array[0].Serialize(hash)
	array[1].Serialize(hash)
	var localHash core.Byte128
	copy(localHash[:], hash.Sum(nil)[:16])

	info := client.GetAccountInfo()
	if reflect.TypeOf(info).String() != "*core.MsgServerAccountInfo" {
		t.Error("Invalid response to client.GetAccountInfo")
	}
	if len(info.DatasetList) != 1 {
		t.Error("More than one dataset was found under test account")
	} else {
		if info.DatasetList[0].Name != "testset" {
			t.Error("First dataset is not named \"testset\"")
		}
		if fmt.Sprintf("%x", info.DatasetList[0].ListH) != fmt.Sprintf("%x", localHash) {
			t.Error(fmt.Sprintf("%x != %x", info.DatasetList[0].ListH, localHash))
			t.Error("List hash could not be verified")
		}
		if info.DatasetList[0].Size != 33509 {
			t.Error(fmt.Sprintf("Wrong total size for the dataset %d != %d", info.DatasetList[0].Size, 33509))
		}
	}

	list := client.ListDataset("testset")
	if list == nil {
		t.Error("Dataset \"testset\" was not found")
	} else if !reflect.DeepEqual(array, list.States) {
		fmt.Println(array)
		fmt.Println(list.States)
		t.Error("Local list and remote list not equal")
	}
}