Documentation
¶
Overview ¶
Package authz decides whether a RustDesk connection may start and which control permissions the controlled device applies to it, from the connection rules and control roles (docs/acl-policy.md).
hbbs (bropines/rustdesk-server with AUTHZ_URL set) asks the panel at POST /internal/hbbs/authorize for every punch-hole and relay request and attaches the returned permissions to the request it forwards to the device (ControlPermissions; honoured by RustDesk 1.4.5 and later on desktop platforms). The same decision backs the after-the-fact kick of the client API's audit handler.
Index ¶
Constants ¶
const ( CauseUnknownDevice = "unknown_device" CauseAdmin = "admin" CauseAnonymous = "anonymous" CauseNoRules = "no_rules" CauseOwner = "owner" CauseRule = "rule" CauseDefaultDeny = "default_deny" CauseConnType = "conn_type" )
Causes (Decision.Cause) are short, fixed strings for logs.
const ( ReasonSignIn = "Sign in to connect: access rules apply" ReasonDefaultDeny = "No access rule allows this connection" )
Reasons shown to the controller when a connection is denied.
const ( ResultAllow = "allow" ResultDeny = "deny" ResultError = "error" )
Metric results.
const MaxBody = 4 << 10
MaxBody bounds the request body.
const Path = "/internal/hbbs/authorize"
Path is where the endpoint is mounted on the panel's root router (outside /api: it is not part of the admin API contract).
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ConnType ¶
type ConnType int
ConnType is the rendezvous ConnType of a request (hbb_common rendezvous.proto), as hbbs reports it in "conn_type".
const ( ConnDefault ConnType = 0 // remote desktop ConnFileTransfer ConnType = 1 ConnPortForward ConnType = 2 ConnRDP ConnType = 3 ConnViewCamera ConnType = 4 ConnTerminal ConnType = 5 )
Connection types.
func AuditConnType ¶
AuditConnType maps the "type" of a client's /api/audit/conn record (0 remote desktop, 1 file transfer, 2 port forward or RDP, 3 view camera, 4 terminal) to a ConnType.
type Decision ¶
type Decision struct {
Allow bool
// Permissions restrict an allowed connection (0 = device settings).
Permissions Permissions
// Reason is shown to the controller when the connection is denied.
Reason string
// Cause, UserID (0 = anonymous), Rule and Role explain the decision in
// logs.
Cause string
UserID int64
Rule string
Role string
}
Decision is the outcome for one connection.
func Decide ¶
func Decide(ctx context.Context, acl *store.ConnectionACLs, user *store.User, d *store.Device, ct ConnType) (Decision, error)
Decide is the policy for a connection of user (nil: anonymous or unknown controller) to the registered device d:
- active admins are never restricted;
- while any connection rule is enabled, anonymous controllers are denied and users get the rules' decision (store.ConnectionACLs.Evaluate); without enabled rules everyone is allowed;
- an allowed connection runs under its effective control role (the matching rule's role, else the default role): what the role does not allow is disabled, and file transfer, port forwarding / RDP and terminal connections are denied outright when the role forbids them.
Disabled users count as anonymous.
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler serves POST Path for hbbs. Anything but a POST from a loopback TCP peer without proxy headers and with the shared secret as bearer token gets the same 404 as an unknown path.
func NewHandler ¶
func NewHandler(svc *Service, secret, realIPHeader string, reg prometheus.Registerer, log *slog.Logger) (*Handler, error)
NewHandler returns the endpoint for svc. secret is the bearer secret hbbs presents (AUTHZ_SECRET_FILE); realIPHeader is the panel's configured client-IP header (also refused); reg may be nil.
type Permission ¶
type Permission uint8
Permission is a RustDesk ControlPermissions.Permission value (hbb_common rendezvous.proto); its state lives at bit 2*Permission of the bitmap.
const ( PermKeyboard Permission = 0 PermRemotePrinter Permission = 1 PermClipboard Permission = 2 PermFile Permission = 3 PermAudio Permission = 4 PermCamera Permission = 5 PermTerminal Permission = 6 PermTunnel Permission = 7 PermRestart Permission = 8 PermRecording Permission = 9 PermBlockInput Permission = 10 PermRemoteModify Permission = 11 PermPrivacyMode Permission = 12 PermUSB Permission = 13 )
Permissions known to RustDesk clients.
type Permissions ¶
type Permissions uint64
Permissions is the ControlPermissions.permissions bitmap (u64, 2 bits per permission). The zero value sets nothing: the device's settings apply.
func RolePermissions ¶
func RolePermissions(r *store.ControlRole) Permissions
RolePermissions is the bitmap for a connection under control role r: every capability the role does not allow is disabled, everything else is left unset so the device owner's local settings still apply. A nil role or a role allowing everything yields 0.
func (Permissions) State ¶
func (p Permissions) State(perm Permission) State
State returns the state of perm in p.
func (Permissions) String ¶
func (p Permissions) String() string
String is the decimal form hbbs expects in the "permissions" field.
func (Permissions) With ¶
func (p Permissions) With(perm Permission, s State) Permissions
With returns p with perm set to s.
type Request ¶
type Request struct {
// TargetID is the RustDesk id of the device being connected to.
TargetID string `json:"target_id"`
// Token is the controller's client token ("" when not signed in).
Token string `json:"token"`
// ConnType is the rendezvous ConnType.
ConnType ConnType `json:"conn_type"`
// ControllerIP and Kind ("punch_hole" or "request_relay") are only
// logged.
ControllerIP string `json:"controller_ip"`
Kind string `json:"kind"`
}
Request is the body hbbs posts for a punch-hole or relay request.
type Response ¶
type Response struct {
Allow bool `json:"allow"`
// Permissions is the ControlPermissions bitmap as a decimal string (u64
// does not survive JSON numbers in every parser).
Permissions string `json:"permissions"`
// Reason is shown to the controller when Allow is false.
Reason string `json:"reason"`
}
Response is the body returned to hbbs.
type Service ¶
type Service struct {
Store *store.Store
// JWT verifies controller tokens (the panel's client token key, shared
// with hbbs).
JWT *auth.ClientJWT
}
Service decides hbbs requests.
func (*Service) Authorize ¶
Authorize decides req. Devices the panel does not know are not restricted.
func (*Service) Controller ¶
Controller resolves a controller's client token to its user. It is nil (anonymous) for an empty, malformed, mis-signed or expired token, a token the panel recorded and that was since revoked or expired (sign-out, admin revocation, sliding expiry), and an unknown or disabled user. Tokens the panel signed without recording them (the web client's short-lived ones) are accepted on their signature, as hbbs does for MUST_LOGIN.
type State ¶
type State uint8
State is the 2-bit state of one permission.
Permission states. NotSet leaves the decision to the device's own setting; Disable turns the capability off for the connection; Enable turns it on even when the device owner disabled it (never sent by RD Panel: roles only restrict).