blob: 47dcc7419de27531a081839575df6623c5b35f1f [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/// Options for [`Directory.Open`] and [`Node.Reopen`].
type ConnectionOptions = table {
/// Flags which can affect the behavior when opening and reopening.
/// If absent, assumes a default of zero.
1: flags @generated_name("ConnectionFlags") strict bits : uint64 {
/// Requests that an [`Node.OnConnectionInfo`] event be sent as the first
/// message on the protocol request. Requests all fields in the
/// [`ConnectionInfo`] table. Doing so is more efficient than calling
/// [`Node.Describe`] later on the connection.
/// Connects to the exposed protocol if the node is a Connector.
/// It is an error to use this flag with other types of nodes.
/// If both `GET_CONNECTION_INFO` and `CONNECT` are specified, the channel
/// will receive exactly one [`Node.OnConnectionInfo`] event, after which
/// the protocol switches from [`Node`] to the intended protocol.
/// Message sent by the client prior to receiving [`Node.OnConnectionInfo`]
/// are queued and processed after the protocol switch.
/// `CONNECT` cannot be supplied together with `APPEND`.
/// `CONNECT` cannot be supplied together with `TRUNCATE`.
/// Requires the [`Rights.CONNECT`] right on the connection.
CONNECT = 0x02;
/// Opens the node in append mode, i.e. the connection should seek to the
/// end of the node before every write.
/// If the node does not support appending, it should result in a
/// `ZX_ERR_NOT_SUPPORTED` epitaph.
/// Currently, only [`NodeProtocols.FILE`] connections
/// may be configured for appending.
APPEND = 0x04;
/// Truncates the object before usage, by setting its length to 0.
/// Requires the [`Rights.WRITE_BYTES`] right on the connection.
/// If the node does not support truncating, it should result in a
/// `ZX_ERR_NOT_SUPPORTED` epitaph.
TRUNCATE = 0x08;
/// Specifies the set of representations accepted by the client, to support
/// a form of protocol negotiation on the node being opened.
/// Refer to the definition of [`NodeProtocols`] for more details.
/// It cannot be zero.
/// In addition, clients may assert the type of the object by setting
/// the protocol corresponding to the expected type:
/// * If the caller expected a directory but the node cannot be accessed
/// as a directory, the error is `ZX_ERR_NOT_DIR`.
/// * If the caller expected a file but the node cannot be accessed as a
/// file, the error is `ZX_ERR_NOT_FILE`.
/// * In other mismatched cases, the error is `ZX_ERR_WRONG_TYPE`.
/// During [`Directory.Open`], if a new object is to be created, `protocols`
/// determines the type of object to create; it must be present.
/// If a valid object type cannot be unambiguously inferred e.g.
/// both `DIRECTORY` and `FILE` were set, the request must fail.
/// During [`Node.Reopen`], clients may specify a different but compatible
/// `protocols` to do a "protocol upgrade".
/// If more than one protocol is present in `protocols`, the resultant
/// protocol may become any one of them. Clients should specify
/// [`ConnectionFlags.GET_CONNECTION_INFO`] to receive a
/// [`Node.OnConnectionInfo`] event, in order to ascertain the protocol.
/// If absent, indicates that the caller accepts any type of node, and
/// the resulting protocol is unspecified.
2: protocols NodeProtocols;
/// Requests rights on the new connection according to the specified rules.
/// See [`RightsRequest`].
/// ## Rights Hierarchy
/// Respecting principles of least privileges, rights in general must meet
/// the following restrictions:
/// * A connection must have nonzero rights.
/// * From the perspective of a client, rights must never increase in a
/// derived connection.
/// * From the perspective of a directory proxy, it must ensure that
/// new connections opened through it cannot have more rights than
/// the connection where the proxy received the `Open`/`Reopen` call.
/// The proper enforcement of the rights hierarchy is a powerful refinement
/// over the existing access control facilities offered by directory
/// sandboxing.
/// ## Rights Inheritance
/// If `rights_request` is absent, inherits at most the rights on the source
/// connection:
/// * During [`Node.Reopen`], the new connection would have the same rights
/// as the connection where the `Reopen` call is made.
/// * During [`Directory.Open`], the rights on the connection would inherit
/// from the connection where the `Open` call is made. If the path crosses
/// intermediate proxies, a proxy may strip elements from the resulting
/// rights if the intermediate connection does not have the corresponding
/// rights.
/// ## Rights vs Abilities
/// The rights on a connection limits the set of operations allowed on that
/// connection, but does not guarantee their availability, because the
/// object may not support it. For convenience, clients may query the
/// [`ConnectionInfo.available_operations`] field on a new connection,
/// which is the intersection of the rights and abilities and indicates the
/// guaranteed set of available operations.
/// See [`Rights`] and [`Abilities`].
/// ## Implementation Notes
/// When a directory proxy encounters an absent `rights` field, let `r` be
/// the rights on the connection where it received this request, the proxy
/// should fill in this field with the following:
/// ```
/// RightsRequest {
/// at_most: r,
/// at_least: 0,
/// resolution: RightsResolution.MAXIMIZE,
/// }
/// ```
/// before forwarding the request to the remote party.
/// Options for requesting rights on the new connection. Because opening a
/// new connection may involve multiple hops through directory proxies,
/// we require the client to set an upper bound and lower bound on the
/// rights request, and intermediate proxies to refine these bounds.
/// The rights manipulation should be implemented mechanically
/// without knowledge of any specific rights, and servers should propagate
/// unknown bits members, to gracefully handle future rights extensions.
/// ## Implementation Notes
/// It could be common for a client to request an exact set of rights.
/// We recommend client libraries to define a helper function like follows:
/// ```
/// fn Exact(exact_rights: Rights) -> RightsRequest {
/// RightsRequest {
/// at_most: exact_rights,
/// at_least: exact_rights,
/// resolution: RightsResolution.MAXIMIZE,
/// }
/// }
/// ```
3: rights_request @generated_name("RightsRequest") struct {
/// Sets an upper bound on the resulting rights. The exact rights will
/// depend on `resolution`.
/// ## Implementation Notes
/// When a directory proxy encounters this variant, it should compute the
/// intersection between this and the rights on the connection where it
/// received the request, to shrink the rights.
/// * If the intersection is empty, or not a superset of `at_least`,
/// the proxy should close `object_request` with the
/// `ZX_ERR_ACCESS_DENIED` epitaph.
/// * Otherwise, the proxy should forward the `Open` call as usual,
/// but update `at_most` with the shrunk rights.
at_most Rights;
/// Sets a lower bound on the resulting rights. The exact rights will
/// depend on `resolution`.
/// + During [`Directory.Open`], you may only specify the same rights as
/// what the directory connection already has, or a subset of those.
/// + During [`Node.Reopen`], similarly, you may only specify the same or
/// a subset of rights possessed by the original connection.
/// + Exceeding those rights causes `object_request` to be closed with a
/// `ZX_ERR_ACCESS_DENIED` epitaph.
/// Therefore there are these invariants which should be maintained:
/// ```
/// at_most ⊋ {}
/// at_most ⊃ at_least
/// rights_on_connection_where_open_is_received ⊋ {}
/// rights_on_connection_where_open_is_received ⊃ at_least
/// ```
/// using the superset (`⊃`), proper superset (`⊋`),
/// and empty set (`{}`) notations.
at_least Rights;
/// When an `Open`/`Reopen` request reaches its final remote server, it should
/// assign rights on the new connection based on one of these modes.
resolution @generated_name("RightsResolution") strict enum : uint32 {
/// The rights will be the intersection between [`RightsRequest.at_most`]
/// and the connection where the `Open`/`Reopen` request was received,
/// closing `object_request` with `ZX_ERR_ACCESS_DENIED` if it is empty.
/// The rights will be determined by the following rules:
/// * If the negotiated protocol on the new connection is
/// [`Directory`], the rules from the `MAXIMIZE` case applies.
/// * Otherwise, the rights will be [`RightsRequest.at_least`] if it
/// does not exceed rights on the current connection.
/// * Otherwise, `object_request` should be closed with
/// The motivation for this enum is to facilitate implementing POSIX
/// compatibility layers. The POSIX file permission model relies on ambient
/// authority: access control on files are resolved based on the `mode` of
/// the file, and the current user. There is no concept of hierarchical
/// permissions. Fuchsia, on the other hand, restricts rights on file
/// connections to never exceed that of its containing directory connection.
POSIX = 2;