Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F13520171
verification-tracker.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
9 KB
Referenced Files
None
Subscribers
None
verification-tracker.cpp
View Options
/*
* This file is part of libkazv.
* SPDX-FileCopyrightText: 2021 Tusooa Zhu <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include
<libkazv-config.hpp>
#include
<algorithm>
#include
<immer/set.hpp>
#include
<types.hpp>
#include
<debug.hpp>
#include
"verification-tracker.hpp"
#include
"verification-process.hpp"
namespace
Kazv
{
using
namespace
VerificationTrackerActions
;
using
TrackerAct
=
VerificationTrackerAction
;
using
TrackerRes
=
VerificationTrackerResult
;
static
const
auto
supportedVerificationMethods
=
immer
::
set
<
std
::
string
>
{}.
insert
(
"m.sas.v1"
);
static
bool
methodSupported
(
immer
::
flex_vector
<
std
::
string
>
methods
)
{
return
std
::
any_of
(
methods
.
begin
(),
methods
.
end
(),
[](
auto
method
)
{
return
supportedVerificationMethods
.
count
(
method
);
});
}
std
::
string
idealMethod
(
immer
::
flex_vector
<
std
::
string
>
/* methods */
)
{
return
SASVerificationProcess
::
name
();
}
static
std
::
size_t
processRequestRandomSize
(
std
::
string
method
)
{
if
(
method
==
SASVerificationProcess
::
name
())
{
return
SASVerificationProcess
::
constructRandomSize
();
}
return
0
;
}
static
std
::
size_t
processStartRandomSize
(
std
::
string
method
)
{
if
(
method
==
SASVerificationProcess
::
name
())
{
return
SASVerificationProcess
::
constructRandomSize
();
}
return
0
;
}
static
bool
isEventWellFormed
(
const
nlohmann
::
json
&
event
)
{
return
event
.
is_object
()
&&
event
.
contains
(
"content"
)
&&
event
[
"content"
].
is_object
()
&&
event
.
contains
(
"type"
)
&&
event
[
"type"
].
is_string
()
&&
event
[
"content"
].
contains
(
"from_device"
)
&&
event
[
"content"
][
"from_device"
].
is_string
()
&&
(
event
[
"content"
].
contains
(
"transaction_id"
)
&&
event
[
"content"
][
"transaction_id"
].
is_string
()
);
}
namespace
{
enum
CheckStatus
{
Ok
,
NotOfType
,
NotWellFormed
};
}
static
CheckStatus
isRequest
(
const
nlohmann
::
json
&
event
)
{
if
(
!
(
event
[
"type"
].
template
get
<
std
::
string
>
()
==
"m.key.verification.request"
))
{
return
NotOfType
;
}
if
(
!
(
event
[
"content"
].
contains
(
"methods"
)
&&
event
[
"content"
][
"methods"
].
is_array
()))
{
kzo
.
crypto
.
dbg
()
<<
"methods not an array"
<<
std
::
endl
;
return
NotWellFormed
;
}
return
Ok
;
}
static
CheckStatus
isReady
(
const
nlohmann
::
json
&
event
)
{
if
(
!
(
event
[
"type"
].
template
get
<
std
::
string
>
()
==
"m.key.verification.ready"
))
{
return
NotOfType
;
}
if
(
!
(
event
[
"content"
].
contains
(
"methods"
)
&&
event
[
"content"
][
"methods"
].
is_array
()))
{
kzo
.
crypto
.
dbg
()
<<
"methods not an array"
<<
std
::
endl
;
return
NotWellFormed
;
}
return
Ok
;
}
using
Methods
=
immer
::
flex_vector
<
std
::
string
>
;
static
Methods
methodsForEvent
(
const
nlohmann
::
json
&
event
)
{
return
event
[
"content"
][
"methods"
]
.
template
get
<
immer
::
flex_vector
<
std
::
string
>>
();
}
struct
VerificationTracker
::
Private
{
std
::
string
userId
;
std
::
string
deviceId
;
using
ProcessMap
=
std
::
unordered_map
<
std
::
string
,
std
::
unordered_map
<
std
::
string
,
VerificationProcess
>>
;
ProcessMap
processes
;
nlohmann
::
json
makeEvent
(
std
::
string
type
,
Timestamp
ts
,
std
::
string
txnId
,
nlohmann
::
json
content
)
const
;
std
::
string
nextTxnId
(
Timestamp
ts
);
bool
hasExistingProcessForIncomingEvent
(
const
nlohmann
::
json
&
event
)
const
;
void
addProcess
(
std
::
string
userId
,
immer
::
flex_vector
<
std
::
string
>
deviceIds
,
VerificationProcess
process
);
void
removeProcess
(
std
::
string
userId
,
immer
::
flex_vector
<
std
::
string
>
deviceIds
);
};
nlohmann
::
json
VerificationTracker::Private::makeEvent
(
std
::
string
type
,
Timestamp
ts
,
std
::
string
txnId
,
nlohmann
::
json
content
)
const
{
auto
ev
=
nlohmann
::
json
{
{
"type"
,
type
},
{
"content"
,
content
}
};
ev
[
"content"
][
"from_device"
]
=
deviceId
;
ev
[
"content"
][
"timestamp"
]
=
ts
;
ev
[
"content"
][
"transaction_id"
]
=
txnId
;
return
ev
;
}
std
::
string
VerificationTracker::Private::nextTxnId
(
Timestamp
ts
)
{
return
std
::
to_string
(
ts
);
}
void
VerificationTracker::Private::addProcess
(
std
::
string
userId
,
immer
::
flex_vector
<
std
::
string
>
deviceIds
,
VerificationProcess
process
)
{
for
(
auto
deviceId
:
deviceIds
)
{
processes
.
try_emplace
(
userId
);
processes
[
userId
][
deviceId
]
=
process
;
}
}
VerificationTracker
::
VerificationTracker
()
:
m_d
(
new
Private
{})
{
}
VerificationTracker
::
VerificationTracker
(
std
::
string
userId
,
std
::
string
deviceId
)
:
m_d
(
new
Private
{
userId
,
deviceId
,
{}})
{
}
KAZV_DEFINE_COPYABLE_UNIQUE_PTR
(
VerificationTracker
,
m_d
);
VerificationTracker
::~
VerificationTracker
()
=
default
;
std
::
size_t
VerificationTracker::processRandomSize
(
const
nlohmann
::
json
&
event
)
{
if
(
!
isEventWellFormed
(
event
))
{
return
0
;
}
kzo
.
crypto
.
dbg
()
<<
"event: "
<<
event
.
dump
()
<<
std
::
endl
;
auto
checkRequestRes
=
isRequest
(
event
);
if
(
checkRequestRes
==
NotWellFormed
)
{
return
0
;
}
if
(
checkRequestRes
!=
NotOfType
)
{
auto
methods
=
methodsForEvent
(
event
);
if
(
methodSupported
(
methods
))
{
kzo
.
crypto
.
dbg
()
<<
"methods supported"
<<
std
::
endl
;
return
processRequestRandomSize
(
idealMethod
(
methods
));
}
kzo
.
crypto
.
dbg
()
<<
"methods not supported"
<<
std
::
endl
;
return
0
;
}
if
(
event
[
"type"
].
template
get
<
std
::
string
>
()
==
"m.key.verification.start"
)
{
if
(
!
(
event
[
"content"
].
contains
(
"method"
)
&&
event
[
"content"
][
"method"
].
is_string
()))
{
return
0
;
}
auto
method
=
event
[
"content"
][
"method"
]
.
template
get
<
std
::
string
>
();
if
(
methodSupported
({
method
}))
{
return
processStartRandomSize
(
method
);
}
return
0
;
}
return
0
;
}
VerificationTrackerResult
VerificationTracker::process
(
std
::
string
theirUserId
,
const
nlohmann
::
json
&
event
,
RandomData
random
,
Timestamp
ts
)
{
auto
sendCancel
=
TrackerRes
{};
// TODO
if
(
!
isEventWellFormed
(
event
))
{
return
sendCancel
;
}
// Process request event
auto
checkRequestRes
=
isRequest
(
event
);
if
(
checkRequestRes
!=
NotOfType
)
{
if
(
checkRequestRes
==
NotWellFormed
)
{
return
sendCancel
;
}
auto
methods
=
event
[
"content"
][
"methods"
]
.
template
get
<
immer
::
flex_vector
<
std
::
string
>>
();
if
(
!
methodSupported
(
methods
))
{
kzo
.
crypto
.
warn
()
<<
"We do not support any methods provided."
<<
std
::
endl
;
return
sendCancel
;
}
auto
methodToUse
=
idealMethod
(
methods
);
kzo
.
crypto
.
dbg
()
<<
"choosing method: "
<<
methodToUse
<<
std
::
endl
;
auto
theirDeviceId
=
event
[
"content"
][
"from_device"
].
template
get
<
std
::
string
>
();
auto
txnId
=
m_d
->
nextTxnId
(
ts
);
m_d
->
addProcess
(
theirUserId
,
{
theirDeviceId
},
VerificationProcess
(
VerificationProcess
::
ToDeviceTag
{},
ts
,
txnId
,
methods
));
auto
notifyAction
=
TrackerAct
{
ShowStatus
{
theirUserId
,
theirDeviceId
,
ShowStatus
::
Status
::
Requested
}};
auto
sendReadyAction
=
TrackerAct
{
SendEvent
{
theirUserId
,
{
theirDeviceId
},
m_d
->
makeEvent
(
"m.key.verification.ready"
,
ts
,
txnId
,
nlohmann
::
json
::
object
({{
"methods"
,
nlohmann
::
json
::
array
({
methodToUse
})}})
)
}};
auto
sendStartAction
=
TrackerAct
{
SendEvent
{
theirUserId
,
{
theirDeviceId
},
m_d
->
makeEvent
(
"m.key.verification.start"
,
ts
,
txnId
,
m_d
->
processes
[
theirUserId
][
theirDeviceId
].
obtainStartEventContent
(
random
)
)
}};
return
TrackerRes
{
notifyAction
,
sendReadyAction
,
sendStartAction
};
}
return
{};
}
VerificationTrackerResult
VerificationTracker::requestVerification
(
std
::
string
userId
,
immer
::
flex_vector
<
std
::
string
>
deviceIds
,
Timestamp
ts
)
{
auto
txnId
=
m_d
->
nextTxnId
(
ts
);
auto
methods
=
immer
::
flex_vector
<
std
::
string
>
(
supportedVerificationMethods
.
begin
(),
supportedVerificationMethods
.
end
());
auto
proc
=
VerificationProcess
(
VerificationProcess
::
ToDeviceTag
{},
ts
,
txnId
,
methods
);
m_d
->
addProcess
(
userId
,
deviceIds
,
proc
);
auto
sendEventAction
=
TrackerAct
(
SendEvent
{
userId
,
deviceIds
,
m_d
->
makeEvent
(
"m.key.verification.request"
,
ts
,
txnId
,
nlohmann
::
json
::
object
({{
"methods"
,
methods
}})
)
});
return
TrackerRes
{
sendEventAction
};
}
}
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Sun, Dec 7, 7:25 PM (1 d, 12 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
700120
Default Alt Text
verification-tracker.cpp (9 KB)
Attached To
Mode
rL libkazv
Attached
Detach File
Event Timeline
Log In to Comment