Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
I
irmago
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Jobs
Commits
Open sidebar
IRMA
Github mirrors
irmago
Commits
8d0c0554
Commit
8d0c0554
authored
Aug 08, 2019
by
Sietse Ringers
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: add revocation server endpoints to servercore
parent
33c3b9b6
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
116 additions
and
11 deletions
+116
-11
internal/servercore/api.go
internal/servercore/api.go
+93
-8
server/api.go
server/api.go
+21
-1
server/irmaserver/main.go
server/irmaserver/main.go
+2
-2
No files found.
internal/servercore/api.go
View file @
8d0c0554
...
...
@@ -10,6 +10,7 @@ import (
"net/http"
"path/filepath"
"regexp"
"strconv"
"strings"
"time"
...
...
@@ -17,6 +18,7 @@ import (
"github.com/jasonlvhit/gocron"
"github.com/privacybydesign/gabi"
"github.com/privacybydesign/gabi/big"
"github.com/privacybydesign/gabi/revocation"
"github.com/privacybydesign/irmago"
"github.com/privacybydesign/irmago/internal/fs"
"github.com/privacybydesign/irmago/server"
...
...
@@ -168,6 +170,7 @@ func (s *Server) verifyPrivateKeys(configuration *server.Configuration) error {
if
err
=
db
.
LoadCurrent
();
err
!=
nil
{
return
server
.
LogError
(
err
)
}
s
.
conf
.
RevocableCredentials
[
credid
]
=
struct
{}{}
}
}
}
...
...
@@ -293,13 +296,21 @@ func (s *Server) CancelSession(token string) error {
return
nil
}
func
ParsePath
(
path
string
)
(
string
,
string
,
error
)
{
pattern
:=
regexp
.
MustCompile
(
"session/(
\\
w+)/?(|commitments|proofs|status|statusevents)$"
)
matches
:=
pattern
.
FindStringSubmatch
(
path
)
if
len
(
matches
)
!
=
3
{
return
""
,
""
,
server
.
LogWarning
(
errors
.
Errorf
(
"Invalid URL: %s"
,
path
))
func
ParsePath
(
path
string
)
(
token
,
noun
string
,
arg
[]
string
,
err
error
)
{
client
:=
regexp
.
MustCompile
(
"session/(
\\
w+)/?(|commitments|proofs|status|statusevents)$"
)
matches
:=
client
.
FindStringSubmatch
(
path
)
if
len
(
matches
)
=
=
3
{
return
matches
[
1
],
matches
[
2
],
nil
,
nil
}
return
matches
[
1
],
matches
[
2
],
nil
rev
:=
regexp
.
MustCompile
(
"-/revocation/(records)/?(.*)$"
)
matches
=
rev
.
FindStringSubmatch
(
path
)
if
len
(
matches
)
==
3
{
args
:=
strings
.
Split
(
matches
[
2
],
"/"
)
return
""
,
matches
[
1
],
args
,
nil
}
return
""
,
""
,
nil
,
server
.
LogWarning
(
errors
.
Errorf
(
"Invalid URL: %s"
,
path
))
}
func
(
s
*
Server
)
SubscribeServerSentEvents
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
token
string
,
requestor
bool
)
error
{
...
...
@@ -375,12 +386,22 @@ func (s *Server) handleProtocolMessage(
}
}
token
,
noun
,
err
:=
ParsePath
(
path
)
token
,
noun
,
args
,
err
:=
ParsePath
(
path
)
if
err
!=
nil
{
status
,
output
=
server
.
JsonResponse
(
nil
,
server
.
RemoteError
(
server
.
ErrorUnsupported
,
""
))
return
}
if
token
!=
""
{
status
,
output
,
result
=
s
.
handleClientMessage
(
token
,
noun
,
method
,
headers
,
message
)
}
else
{
status
,
output
=
s
.
handleRevocationMessage
(
noun
,
method
,
args
,
headers
,
message
)
}
return
}
func
(
s
*
Server
)
handleClientMessage
(
token
,
noun
,
method
string
,
headers
map
[
string
][]
string
,
message
[]
byte
,
)
(
status
int
,
output
[]
byte
,
result
*
server
.
SessionResult
)
{
// Fetch the session
session
:=
s
.
sessions
.
clientGet
(
token
)
if
session
==
nil
{
...
...
@@ -498,3 +519,67 @@ func (s *Server) handleProtocolMessage(
return
}
}
func
(
s
*
Server
)
handleRevocationMessage
(
noun
,
method
string
,
args
[]
string
,
headers
map
[
string
][]
string
,
message
[]
byte
,
)
(
int
,
[]
byte
)
{
if
noun
==
"records"
&&
method
==
http
.
MethodGet
{
if
len
(
args
)
!=
2
{
return
server
.
JsonResponse
(
nil
,
server
.
RemoteError
(
server
.
ErrorInvalidRequest
,
"GET records expects 2 url arguments"
))
}
index
,
err
:=
strconv
.
Atoi
(
args
[
1
])
if
err
!=
nil
{
return
server
.
JsonResponse
(
nil
,
server
.
RemoteError
(
server
.
ErrorMalformedInput
,
err
.
Error
()))
}
cred
:=
irma
.
NewCredentialTypeIdentifier
(
args
[
0
])
return
server
.
JsonResponse
(
s
.
handleGetRevocationRecords
(
cred
,
index
))
}
if
noun
==
"records"
&&
method
==
http
.
MethodPost
{
if
len
(
args
)
!=
1
{
return
server
.
JsonResponse
(
nil
,
server
.
RemoteError
(
server
.
ErrorInvalidRequest
,
"POST records expects 1 url arguments"
))
}
cred
:=
irma
.
NewCredentialTypeIdentifier
(
args
[
0
])
var
records
[]
*
revocation
.
Record
if
err
:=
json
.
Unmarshal
(
message
,
&
records
);
err
!=
nil
{
return
server
.
JsonResponse
(
nil
,
server
.
RemoteError
(
server
.
ErrorMalformedInput
,
err
.
Error
()))
}
return
server
.
JsonResponse
(
s
.
handlePostRevocationRecords
(
cred
,
records
))
}
return
server
.
JsonResponse
(
nil
,
server
.
RemoteError
(
server
.
ErrorInvalidRequest
,
""
))
}
func
(
s
*
Server
)
handlePostRevocationRecords
(
cred
irma
.
CredentialTypeIdentifier
,
records
[]
*
revocation
.
Record
,
)
(
interface
{},
*
irma
.
RemoteError
)
{
if
_
,
ok
:=
s
.
conf
.
RevocableCredentials
[
cred
];
!
ok
{
return
nil
,
server
.
RemoteError
(
server
.
ErrorInvalidRequest
,
"not supported by this server"
)
}
db
,
err
:=
s
.
conf
.
IrmaConfiguration
.
RevocationDB
(
cred
)
if
err
!=
nil
{
return
nil
,
server
.
RemoteError
(
server
.
ErrorUnknown
,
err
.
Error
())
// TODO error type
}
for
_
,
r
:=
range
records
{
if
err
=
db
.
Add
(
r
.
Message
,
r
.
PublicKeyIndex
);
err
!=
nil
{
return
nil
,
server
.
RemoteError
(
server
.
ErrorUnknown
,
err
.
Error
())
// TODO error type
}
}
return
nil
,
nil
}
func
(
s
*
Server
)
handleGetRevocationRecords
(
cred
irma
.
CredentialTypeIdentifier
,
index
int
,
)
([]
revocation
.
Record
,
*
irma
.
RemoteError
)
{
if
_
,
ok
:=
s
.
conf
.
RevocableCredentials
[
cred
];
!
ok
{
return
nil
,
server
.
RemoteError
(
server
.
ErrorInvalidRequest
,
"not supported by this server"
)
}
db
,
err
:=
s
.
conf
.
IrmaConfiguration
.
RevocationDB
(
cred
)
if
err
!=
nil
{
return
nil
,
server
.
RemoteError
(
server
.
ErrorUnknown
,
err
.
Error
())
// TODO error type
}
records
,
err
:=
db
.
RevocationRecords
(
index
)
if
err
!=
nil
{
return
nil
,
server
.
RemoteError
(
server
.
ErrorUnknown
,
err
.
Error
())
// TODO error type
}
return
records
,
nil
}
server/api.go
View file @
8d0c0554
package
server
import
(
"bytes"
"encoding/gob"
"encoding/json"
"fmt"
"io/ioutil"
...
...
@@ -40,6 +42,8 @@ type Configuration struct {
IssuerPrivateKeys
map
[
irma
.
IssuerIdentifier
]
*
gabi
.
PrivateKey
`json:"-"`
// Path at which to store revocation databases
RevocationPath
string
`json:"revocation_path" mapstructure:"revocation_path"`
// Credentials types for which revocation database should be hosted
RevocableCredentials
map
[
irma
.
CredentialTypeIdentifier
]
struct
{}
`json:"-"`
// URL at which the IRMA app can reach this server during sessions
URL
string
`json:"url" mapstructure:"url"`
// Required to be set to true if URL does not begin with https:// in production mode.
...
...
@@ -170,13 +174,29 @@ func RemoteError(err Error, message string) *irma.RemoteError {
// JsonResponse JSON-marshals the specified object or error
// and returns it along with a suitable HTTP status code
func
JsonResponse
(
v
interface
{},
err
*
irma
.
RemoteError
)
(
int
,
[]
byte
)
{
return
encodeValOrError
(
v
,
err
,
json
.
Marshal
)
}
func
GobResponse
(
v
interface
{},
err
*
irma
.
RemoteError
)
(
int
,
[]
byte
)
{
return
encodeValOrError
(
v
,
err
,
gobMarshal
)
}
func
gobMarshal
(
v
interface
{})
([]
byte
,
error
)
{
var
b
bytes
.
Buffer
if
err
:=
gob
.
NewEncoder
(
&
b
)
.
Encode
(
v
);
err
!=
nil
{
return
nil
,
err
}
return
b
.
Bytes
(),
nil
}
func
encodeValOrError
(
v
interface
{},
err
*
irma
.
RemoteError
,
encoder
func
(
interface
{})
([]
byte
,
error
))
(
int
,
[]
byte
)
{
msg
:=
v
status
:=
http
.
StatusOK
if
err
!=
nil
{
msg
=
err
status
=
err
.
Status
}
b
,
e
:=
json
.
Marshal
(
msg
)
b
,
e
:=
encoder
(
msg
)
if
e
!=
nil
{
Logger
.
Error
(
"Failed to serialize response:"
,
e
.
Error
())
return
http
.
StatusInternalServerError
,
nil
...
...
server/irmaserver/main.go
View file @
8d0c0554
...
...
@@ -126,8 +126,8 @@ func (s *Server) HandlerFunc() http.HandlerFunc {
}
}
token
,
noun
,
err
:=
servercore
.
ParsePath
(
r
.
URL
.
Path
)
if
err
==
nil
&&
noun
==
"statusevents"
{
// if err != nil we let it be handled by HandleProtocolMessage below
token
,
noun
,
_
,
err
:=
servercore
.
ParsePath
(
r
.
URL
.
Path
)
if
err
==
nil
&&
token
!=
""
&&
noun
==
"statusevents"
{
// if err != nil we let it be handled by HandleProtocolMessage below
if
err
=
s
.
SubscribeServerSentEvents
(
w
,
r
,
token
,
false
);
err
!=
nil
{
server
.
WriteResponse
(
w
,
nil
,
&
irma
.
RemoteError
{
Status
:
server
.
ErrorUnsupported
.
Status
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment