Skip to main content

ServerPolicy

Trait ServerPolicy 

Source
pub trait ServerPolicy:
    Send
    + Sync
    + 'static {
    // Provided methods
    fn decides_mutations(&self) -> bool { ... }
    fn authorize_mutation(&self, context: &MutationAuthorizationContext) -> bool { ... }
    fn authorize_life_safety_operation(
        &self,
        context: &LifeSafetyOperationAuthorizationContext,
    ) -> bool { ... }
    fn authorize_device_communication_control(
        &self,
        context: &DeviceCommunicationControlAuthorizationContext,
    ) -> bool { ... }
    fn authorize_audit_notification(
        &self,
        context: &AuditNotificationAuthorizationContext,
    ) -> bool { ... }
    fn authorize_unconfirmed_audit_notification(
        &self,
        context: &UnconfirmedAuditNotificationAuthorizationContext,
    ) -> bool { ... }
}
Expand description

The server’s authorization decisions, each with a documented default.

See the module documentation for what it covers, the principal each context carries and the calling rules. Install one with policy(..) on a server builder, or in ServerConfig::policy.

Without any policy installed, the server behaves as these defaults do, except that it allows a covered mutation without decoding it for authorization first; so does a policy whose decides_mutations is false.

Arc<P> and Box<P> are policies when P is, so one policy can be shared or boxed.

Provided Methods§

Source

fn decides_mutations(&self) -> bool

Whether authorize_mutation decides anything (default: true).

When false, the server never asks it: each covered mutation is allowed without being decoded for authorization first, and counted as allowed before the handler runs, exactly as with no policy. A policy that only decides LifeSafetyOperation or Audit receipt returns false so that mutations keep that path. The server may read it more than once for one request, so it must give the same answer for the policy’s lifetime.

Source

fn authorize_mutation(&self, context: &MutationAuthorizationContext) -> bool

Whether to carry out one covered mutation (default: allow).

Asked after DeviceCommunicationControl’s checks, request admission, service decoding and element validation, and before any database change, COV or event work, or Audit record. A denial writes no Audit record; it is counted in BACnetServer::mutation_decision_counters and answered SERVICES / SERVICE_REQUEST_DENIED. MutationPolicy::DenyAll denies without asking.

WritePropertyMultiple asks once per decoded, validated element, in wire order, up to the first it denies, all before the database is write-locked and with no database guard held (#2032); the writes follow under the lock. A denial, or a malformed later element, leaves the elements before it written. Since every element is asked about first, the policy can be asked about an element the request never reaches, when an earlier one fails as it is written. An element whose object appears between the decisions and the writes, so it was never asked about, is denied. The other confirmed services ask once, for the whole decoded request, also with no database guard held.

Every call for a received request runs on Tokio’s blocking pool while the request waits (#2032), so a policy that blocks delays only that request: it holds no runtime worker, and BACnetServer::stop ends without waiting for it (the abandoned call finishes on its own and is ignored). That costs one trip to the pool per request (a WritePropertyMultiple’s elements share one; WriteGroup makes one per Channel), so keep the policy quick all the same. A call that never returns keeps its blocking thread after stop(), and a Tokio runtime waits for blocking tasks when it shuts down, so such a policy keeps the process from exiting. The other authorize_* methods for a received request run the same way.

An inbound WriteGroup asks once per Channel it would write, with no database guard held, no invoke ID and the unconfirmed service in the context. A denial skips that Channel silently (nothing answers an unconfirmed request) and writes no Audit record; the other Channels are decided on their own (#1319).

Source

fn authorize_life_safety_operation( &self, context: &LifeSafetyOperationAuthorizationContext, ) -> bool

Whether to carry out a LifeSafetyOperation (default: deny).

Asked after the request is validated and its object found, with no database guard held, on Tokio’s blocking pool as authorize_mutation is (#2032). A denial is answered SERVICES / SERVICE_REQUEST_DENIED before the object changes.

Source

fn authorize_device_communication_control( &self, context: &DeviceCommunicationControlAuthorizationContext, ) -> bool

Whether to carry out a DeviceCommunicationControl request (default: allow).

Asked after decoding, the password, the deprecated DISABLE refusal, the static DccPolicy and the source restriction; a request any of them refuses never reaches the policy. For DISABLE_INITIATION the disable rate limit is charged only after the policy allows, so a denied requester spends none of that shared budget. Asked with no lock held, on Tokio’s blocking pool as authorize_mutation is (#2032), before the timer is replaced or the state changes. A denial is answered SERVICES / SERVICE_REQUEST_DENIED, changes neither the state nor a running timer, writes no Audit record and is counted in BACnetServer::dcc_outcome_counters as policy_denied_total, which also counts the static source and rate-limit refusals.

Source

fn authorize_audit_notification( &self, context: &AuditNotificationAuthorizationContext, ) -> bool

Whether to store a ConfirmedAuditNotification in the configured Audit Log sink (default: deny).

Asked after the request is decoded and checked against completed receipts, with no database guard held, on Tokio’s blocking pool as authorize_mutation is (#2032). A denial is answered SERVICES / SERVICE_REQUEST_DENIED and stores nothing.

Source

fn authorize_unconfirmed_audit_notification( &self, context: &UnconfirmedAuditNotificationAuthorizationContext, ) -> bool

Whether to store an UnconfirmedAuditNotification in the configured Audit Log sink (default: deny).

Asked after the request is decoded, with no database guard held, on Tokio’s blocking pool as authorize_mutation is (#2032). A denial drops the request silently and stores nothing.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementations on Foreign Types§

Source§

impl<P: ServerPolicy + ?Sized> ServerPolicy for Arc<P>

Source§

impl<P: ServerPolicy + ?Sized> ServerPolicy for Box<P>

Implementors§