a35eb8027e
ensure that every integer conversion fits into the destination type, and for any unchecked ones, annotate why they are safe. additionally, any integers we pass into slice headers need to check that they are not negative. all of our allocations should check for allocation failure and return an error if there was a problem. even though an allocation just failed, we don't pre-allocate the failure because we don't want the callers to free it like they have to with the other errors we return. maybe we should just panic. Change-Id: Id4dfad802d312d35e565041efc9872453c90d793
172 lines
4.7 KiB
Go
172 lines
4.7 KiB
Go
// Copyright (C) 2019 Storj Labs, Inc.
|
|
// See LICENSE for copying information.
|
|
|
|
package main
|
|
|
|
// #include "uplink_definitions.h"
|
|
import "C"
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"unsafe"
|
|
|
|
"storj.io/common/macaroon"
|
|
libuplink "storj.io/storj/lib/uplink"
|
|
)
|
|
|
|
//export new_scope
|
|
// new_scope creates new Scope
|
|
func new_scope(satelliteAddress *C.char, apikeyRef C.APIKeyRef, encAccessRef C.EncryptionAccessRef, cerr **C.char) C.ScopeRef {
|
|
apikey, ok := universe.Get(apikeyRef._handle).(libuplink.APIKey)
|
|
if !ok {
|
|
*cerr = C.CString("invalid apikey")
|
|
return C.ScopeRef{}
|
|
}
|
|
|
|
encAccess, ok := universe.Get(encAccessRef._handle).(*libuplink.EncryptionAccess)
|
|
if !ok {
|
|
*cerr = C.CString("invalid encryption access")
|
|
return C.ScopeRef{}
|
|
}
|
|
|
|
scope := &libuplink.Scope{
|
|
SatelliteAddr: C.GoString(satelliteAddress),
|
|
APIKey: apikey,
|
|
EncryptionAccess: encAccess,
|
|
}
|
|
return C.ScopeRef{_handle: universe.Add(scope)}
|
|
}
|
|
|
|
//export get_scope_satellite_address
|
|
// get_scope_satellite_address gets Scope satellite address
|
|
func get_scope_satellite_address(scopeRef C.ScopeRef, cerr **C.char) *C.char {
|
|
scope, ok := universe.Get(scopeRef._handle).(*libuplink.Scope)
|
|
if !ok {
|
|
*cerr = C.CString("invalid scope")
|
|
return nil
|
|
}
|
|
|
|
return C.CString(scope.SatelliteAddr)
|
|
}
|
|
|
|
//export get_scope_api_key
|
|
// get_scope_api_key gets Scope APIKey
|
|
func get_scope_api_key(scopeRef C.ScopeRef, cerr **C.char) C.APIKeyRef {
|
|
scope, ok := universe.Get(scopeRef._handle).(*libuplink.Scope)
|
|
if !ok {
|
|
*cerr = C.CString("invalid scope")
|
|
return C.APIKeyRef{}
|
|
}
|
|
|
|
return C.APIKeyRef{_handle: universe.Add(scope.APIKey)}
|
|
}
|
|
|
|
//export get_scope_enc_access
|
|
// get_scope_enc_access gets Scope encryption access
|
|
func get_scope_enc_access(scopeRef C.ScopeRef, cerr **C.char) C.EncryptionAccessRef {
|
|
scope, ok := universe.Get(scopeRef._handle).(*libuplink.Scope)
|
|
if !ok {
|
|
*cerr = C.CString("invalid scope")
|
|
return C.EncryptionAccessRef{}
|
|
}
|
|
|
|
return C.EncryptionAccessRef{_handle: universe.Add(scope.EncryptionAccess)}
|
|
}
|
|
|
|
//export parse_scope
|
|
// parse_scope parses an Scope
|
|
func parse_scope(val *C.char, cerr **C.char) C.ScopeRef {
|
|
scope, err := libuplink.ParseScope(C.GoString(val))
|
|
if err != nil {
|
|
*cerr = C.CString(fmt.Sprintf("%+v", err))
|
|
return C.ScopeRef{}
|
|
}
|
|
|
|
return C.ScopeRef{_handle: universe.Add(scope)}
|
|
}
|
|
|
|
//export serialize_scope
|
|
// serialize_scope serializes the Scope to a string
|
|
func serialize_scope(scopeRef C.ScopeRef, cerr **C.char) *C.char {
|
|
scope, ok := universe.Get(scopeRef._handle).(*libuplink.Scope)
|
|
if !ok {
|
|
*cerr = C.CString("invalid scope")
|
|
return nil
|
|
}
|
|
|
|
serializedScope, err := scope.Serialize()
|
|
if err != nil {
|
|
*cerr = C.CString(fmt.Sprintf("%+v", err))
|
|
return nil
|
|
}
|
|
|
|
return C.CString(serializedScope)
|
|
}
|
|
|
|
//export restrict_scope
|
|
// restrict_scope restricts a given scope with the provided caveat and encryption restrictions
|
|
func restrict_scope(scopeRef C.ScopeRef, caveat C.Caveat, restrictions **C.EncryptionRestriction, restrictionsLen C.size_t, cerr **C.char) C.ScopeRef {
|
|
scope, ok := universe.Get(scopeRef._handle).(*libuplink.Scope)
|
|
if !ok {
|
|
*cerr = C.CString("invalid scope")
|
|
return C.ScopeRef{}
|
|
}
|
|
|
|
irestrictionsLen, ok := safeConvertToInt(restrictionsLen)
|
|
if !ok || irestrictionsLen < 0 {
|
|
*cerr = C.CString("invalid restrictionsLen: too large or negative")
|
|
return C.ScopeRef{}
|
|
}
|
|
|
|
caveatGo := macaroon.Caveat{
|
|
DisallowReads: bool(caveat.disallow_reads),
|
|
DisallowWrites: bool(caveat.disallow_writes),
|
|
DisallowLists: bool(caveat.disallow_lists),
|
|
DisallowDeletes: bool(caveat.disallow_deletes),
|
|
}
|
|
|
|
apiKeyRestricted, err := scope.APIKey.Restrict(caveatGo)
|
|
if err != nil {
|
|
*cerr = C.CString(fmt.Sprintf("%+v", err))
|
|
return C.ScopeRef{}
|
|
}
|
|
|
|
restrictionsGo := make([]libuplink.EncryptionRestriction, 0, irestrictionsLen)
|
|
if restrictions != nil {
|
|
restrictionsArray := *(*[]C.EncryptionRestriction)(unsafe.Pointer(
|
|
&reflect.SliceHeader{
|
|
Data: uintptr(unsafe.Pointer(restrictions)),
|
|
Len: irestrictionsLen,
|
|
Cap: irestrictionsLen,
|
|
},
|
|
))
|
|
|
|
for _, restriction := range restrictionsArray {
|
|
restrictionsGo = append(restrictionsGo, libuplink.EncryptionRestriction{
|
|
Bucket: C.GoString(restriction.bucket),
|
|
PathPrefix: C.GoString(restriction.path_prefix),
|
|
})
|
|
}
|
|
}
|
|
|
|
apiKeyRestricted, encAccessRestricted, err := scope.EncryptionAccess.Restrict(apiKeyRestricted, restrictionsGo...)
|
|
if err != nil {
|
|
*cerr = C.CString(fmt.Sprintf("%+v", err))
|
|
return C.ScopeRef{}
|
|
}
|
|
|
|
scopeRestricted := &libuplink.Scope{
|
|
SatelliteAddr: scope.SatelliteAddr,
|
|
APIKey: apiKeyRestricted,
|
|
EncryptionAccess: encAccessRestricted,
|
|
}
|
|
return C.ScopeRef{_handle: universe.Add(scopeRestricted)}
|
|
}
|
|
|
|
//export free_scope
|
|
// free_scope frees an scope
|
|
func free_scope(scopeRef C.ScopeRef) {
|
|
universe.Del(scopeRef._handle)
|
|
}
|