Exemplo n.º 1
0
Arquivo: room.go Projeto: logan/heim
func NewRoom(
	ctx scope.Context, kms security.KMS, private bool, name, version string, managers ...proto.Account) (
	proto.ManagedRoom, error) {

	sec, err := proto.NewRoomSecurity(kms, name)
	if err != nil {
		return nil, err
	}

	managerKey := sec.KeyEncryptingKey.Clone()
	if err := kms.DecryptKey(&managerKey); err != nil {
		return nil, err
	}
	roomKeyPair, err := sec.Unlock(&managerKey)
	if err != nil {
		return nil, err
	}

	room := &memRoom{
		RoomBase: RoomBase{
			name:      name,
			version:   version,
			log:       newMemLog(),
			agentBans: map[proto.UserID]time.Time{},
			ipBans:    map[string]time.Time{},
		},
		sec: sec,
		managerKey: &roomManagerKey{
			RoomSecurity: sec,
			GrantManager: &proto.GrantManager{
				Capabilities:     &capabilities{},
				KeyEncryptingKey: &sec.KeyEncryptingKey,
				SubjectKeyPair:   &sec.KeyPair,
				SubjectNonce:     sec.Nonce,
			},
		},
	}
	room.managerKey.GrantManager.Managers = room.managerKey

	var (
		roomMsgKey proto.RoomMessageKey
		msgKey     security.ManagedKey
	)
	if private {
		roomMsgKey, err = room.GenerateMessageKey(ctx, kms)
		if err != nil {
			return nil, err
		}

		msgKey = roomMsgKey.ManagedKey()
		if err := kms.DecryptKey(&msgKey); err != nil {
			return nil, err
		}
	}

	for _, manager := range managers {
		kp := manager.KeyPair()
		c, err := security.GrantPublicKeyCapability(
			kms, sec.Nonce, roomKeyPair, &kp, nil, managerKey.Plaintext)
		if err != nil {
			return nil, err
		}
		room.managerKey.Capabilities.Save(ctx, manager, c)

		if private {
			c, err = security.GrantPublicKeyCapability(
				kms, roomMsgKey.Nonce(), roomKeyPair, &kp, nil, msgKey.Plaintext)
			if err != nil {
				return nil, err
			}
			room.messageKey.Capabilities.Save(ctx, manager, c)
		}
	}

	return room, nil
}
Exemplo n.º 2
0
func (b *Backend) CreateRoom(
	ctx scope.Context, kms security.KMS, private bool, name string, managers ...proto.Account) (
	proto.ManagedRoom, error) {

	sec, err := proto.NewRoomSecurity(kms, name)
	if err != nil {
		return nil, err
	}

	logging.Logger(ctx).Printf("creating room: %s", name)
	room := &Room{
		Name:  name,
		IV:    sec.KeyPair.IV,
		MAC:   sec.MAC,
		Nonce: sec.Nonce,
		EncryptedManagementKey: sec.KeyEncryptingKey.Ciphertext,
		EncryptedPrivateKey:    sec.KeyPair.EncryptedPrivateKey,
		PublicKey:              sec.KeyPair.PublicKey,
	}

	var (
		rmkb   *RoomMessageKeyBinding
		msgKey security.ManagedKey
	)
	if private {
		rmkb, err = room.generateMessageKey(b, kms)
		if err != nil {
			return nil, err
		}

		msgKey = rmkb.ManagedKey()
		if err := kms.DecryptKey(&msgKey); err != nil {
			return nil, err
		}
	}

	// Generate manager capabilities.
	managerKey := sec.KeyEncryptingKey.Clone()
	if err := kms.DecryptKey(&managerKey); err != nil {
		return nil, fmt.Errorf("manager key decrypt error: %s", err)
	}
	roomKeyPair, err := sec.Unlock(&managerKey)
	if err != nil {
		return nil, fmt.Errorf("room security unlock error: %s", err)
	}
	managerCaps := make([]*security.PublicKeyCapability, len(managers))
	for i, manager := range managers {
		kp := manager.KeyPair()
		c, err := security.GrantPublicKeyCapability(
			kms, sec.Nonce, roomKeyPair, &kp, nil, managerKey.Plaintext)
		if err != nil {
			return nil, fmt.Errorf("manager grant error: %s", err)
		}
		managerCaps[i] = c
	}

	accessCaps := []*security.PublicKeyCapability{}
	if private {
		accessCaps = make([]*security.PublicKeyCapability, len(managers))
		for i, manager := range managers {
			kp := manager.KeyPair()
			c, err := security.GrantPublicKeyCapability(
				kms, rmkb.Nonce(), roomKeyPair, &kp, nil, msgKey.Plaintext)
			if err != nil {
				return nil, fmt.Errorf("access grant error: %s", err)
			}
			accessCaps[i] = c
		}
	}

	// Insert data.
	t, err := b.DbMap.Begin()
	if err != nil {
		return nil, err
	}

	rollback := func() {
		if err := t.Rollback(); err != nil {
			logging.Logger(ctx).Printf("rollback error: %s", err)
		}
	}

	if err := t.Insert(room); err != nil {
		logging.Logger(ctx).Printf("room creation error on %s: %s", name, err)
		rollback()
		return nil, err
	}

	if rmkb != nil {
		if err := t.Insert(&rmkb.MessageKey, &rmkb.RoomMessageKey); err != nil {
			logging.Logger(ctx).Printf("room creation error on %s (message key): %s", name, err)
			rollback()
			return nil, err
		}
	}

	managerCapTable := RoomManagerCapabilities{
		Room:     room,
		Executor: t,
	}
	for i, capability := range managerCaps {
		if err := managerCapTable.Save(ctx, managers[i], capability); err != nil {
			logging.Logger(ctx).Printf(
				"room creation error on %s (manager %s): %s", name, managers[i].ID().String(), err)
			rollback()
			return nil, err
		}
	}

	messageCapTable := RoomMessageCapabilities{
		Room:     room,
		Executor: t,
	}
	for i, capability := range accessCaps {
		if err := messageCapTable.Save(ctx, managers[i], capability); err != nil {
			logging.Logger(ctx).Printf(
				"room creation error on %s (access capability): %s", name, err)
			rollback()
			return nil, err
		}
	}

	if err := t.Commit(); err != nil {
		logging.Logger(ctx).Printf("room creation error on %s (commit): %s", name, err)
		return nil, err
	}

	return room.Bind(b), nil
}