Skip to content

rpc2: RPCSEC_GSS privacy service (krb5p) - #109

Open
benjarvis wants to merge 1 commit into
mainfrom
rpcsec-gss-privacy
Open

rpc2: RPCSEC_GSS privacy service (krb5p)#109
benjarvis wants to merge 1 commit into
mainfrom
rpcsec-gss-privacy

Conversation

@benjarvis

Copy link
Copy Markdown
Member

Summary

Adds the RPCSEC_GSS privacy service (krb5p) to the rpc2 GSS layer, completing
the set alongside the krb5/krb5i support merged in #108.

  • Call path: arguments arrive wrapped as rpc_gss_priv_data { opaque databody_priv<> }, where databody_priv is the GSS-sealed token of
    XDR(seq_num) || XDR(proc_args). evpl_rpc2_gss_unwrap_privacy calls the
    provider's unwrap (gss_unwrap), verifies the embedded seq against the
    credential, and repoints the inner proc arguments for normal dispatch.
  • Reply path: evpl_rpc2_gss_wrap_reply_privacy GSS-wraps
    seq_num || results and emits it as the single opaque of rpc_gss_priv_data.
  • EVPL_RPC2_GSS_SVC_PRIVACY is now accepted in the DATA path instead of being
    rejected with AUTH_TOOWEAK.

The crypto stays entirely behind the existing provider vtable (wrap/unwrap),
so libevpl remains Kerberos-free.

Latent fix: GSS unwrap scratch arena overflow

While testing krb5p against the real Linux kernel client, a 256 KiB WRITE
failed to unwrap. Root cause: both the privacy databody_priv token and the
(pre-existing) integrity databody were gathered into the request's fixed
128 KiB dbuf arena (xdr_dbuf_alloc_space), so any wrapped call larger than
the arena returned NULL and failed. This fix mallocs the gather scratch
(bounded by the message size, not the arena) and frees it. The inner iovec
already uses evpl_iovec_alloc, and the reply-wrap paths already use
evpl_iovec_alloc/malloc, so large encrypted READ replies were never
affected — and large krb5i writes are fixed by the same change.

Testing

Validated end-to-end in chimera (the consumer): pynfs 4.1 sec=krb5p smoke +
per-export sec=krb5p policy, and the real Linux kernel client mounting
-o sec=krb5p across four guest kernels (Ubuntu 22.04/24.04/26.04) driving a
multi-block encrypted WRITE+READ. With the arena fix the unwrap failures (and
the client's context-reestablishment retries they triggered) are gone; krb5,
krb5i and krb5p all pass clean. rpc2's own transport ctests pass.

@benjarvis
benjarvis force-pushed the rpcsec-gss-privacy branch from bdf3490 to 13a8f1b Compare June 20, 2026 19:46
Implement the GSS privacy service (rpc_gss_svc_privacy, sec=krb5p) on top of
the existing krb5/krb5i RPCSEC_GSS layer.  Call arguments arrive wrapped as
rpc_gss_priv_data { opaque databody_priv<> } where databody_priv is the
GSS-sealed token of XDR(seq_num) || XDR(proc_args); gss_unwrap recovers the
plaintext, the embedded seq is verified against the credential, and the inner
proc arguments are repointed for normal dispatch.  Replies are wrapped
symmetrically: gss_wrap(seq_num || results) emitted as the single opaque of
rpc_gss_priv_data.  EVPL_RPC2_GSS_SVC_PRIVACY is now accepted in the DATA path
rather than rejected with AUTH_TOOWEAK.

The GSS wrap/unwrap scratch buffers (the privacy databody_priv token, the
integrity databody, and the privacy reply plaintext) need to be contiguous for
the crypto calls.  They previously came from the request's fixed 128 KiB dbuf
arena, so any wrapped call larger than the arena (e.g. a 256 KiB WRITE) failed.
Allocate them from the recycling iovec allocator (evpl_iovec_alloc, max_iovecs
== 1) instead: contiguous, sized to the message, and recycled rather than
malloc/free-churned on every data-path op.  Add evpl_buffer_size() to expose
the allocator's single-buffer contiguous limit.

Bound each length before allocating: it must fit in the bytes actually received
(a raw wire u32 reaches ~4 GiB; the message is already capped at
EVPL_RPC2_MAX_REASM_LENGTH) and within one recycling buffer.  The latter is also
a correctness fix -- evpl_iovec_alloc with max_iovecs == 1 cannot satisfy a
single-iovec request larger than buffer_size and would spin, so an oversized
GSS payload (the existing inner-args allocation included) is now rejected as
malformed rather than hanging the rpc2 thread.  buffer_size (2 MiB default) sits
far above any NFS wsize/rsize.
@benjarvis
benjarvis force-pushed the rpcsec-gss-privacy branch from 13a8f1b to 7acb1b5 Compare June 20, 2026 21:21
benjarvis added a commit to benjarvis/libevpl that referenced this pull request Aug 11, 2026
…himera-nas#109)

* Add REST API for user/share/export/bucket management with Swagger UI

Implement comprehensive REST API endpoints for runtime management of
users, NFS exports, SMB shares, and S3 buckets. Changes are in-memory
only (no persistence).

REST API:
- GET/POST/DELETE /api/v1/users - User management
- GET/POST/DELETE /api/v1/exports - NFS export management
- GET/POST/DELETE /api/v1/shares - SMB share management
- GET/POST/DELETE /api/v1/buckets - S3 bucket management
- GET /api/docs - Embedded Swagger UI
- GET /api/openapi.json - OpenAPI 3.0 specification

Backend additions:
- VFS user cache: builtin user iteration for pinned users
- S3 bucket map: remove and iterate functions
- SMB: share list/get/remove operations
- NFS: export list/get/remove operations
- Server-level wrapper functions for REST handlers

Python SDK:
- Extended chimera_admin.client with all new API methods
- Added API endpoint tests

* Fix Dockerfile pkg-config dependency and reuse lint

- Add pkg-config to both Dockerfiles for REST CMake build
- Break up SPDX strings in embed_files.py to avoid reuse detection

* Update copyright headers to 2025-2026

* License Python admin SDK and OpenAPI spec under Apache-2.0

The admin SDK and OpenAPI specification are intended for broader use
and are licensed under Apache-2.0. Only the C code in chimera remains
LGPL-2.1-only.

* Add HTTPS support to REST API with auto-generated certificates

- Add rest_https_port config option (both HTTP and HTTPS can run simultaneously)
- Add rest_ssl_cert and rest_ssl_key config options for custom certificates
- Auto-generate self-signed certificate at startup if HTTPS enabled but no cert provided
- Update Python SDK client with use_https parameter
- Add HTTPS test fixtures and tests

Config options:
- rest_http_port: HTTP port (default: 0, disabled)
- rest_https_port: HTTPS port (default: 0, disabled)
- rest_ssl_cert: Path to SSL certificate file (optional)
- rest_ssl_key: Path to SSL private key file (optional)

When rest_https_port is set but no certificate is provided, a self-signed
certificate is generated in /tmp/ at startup.

* Add static API documentation with ReDoc

- Add docs/api.html with ReDoc-based OpenAPI viewer
- Move openapi.json to docs/ as single source of truth
- Update CMake to embed spec from docs/openapi.json
- Update docs/index.md with link to API reference
- Add `make docs` target for documentation info

* Fix Docker build by including docs/openapi.json

The CMakeLists.txt for the REST module references docs/openapi.json
for embedding into the build, but .dockerignore was excluding the
entire docs/ directory. Update .dockerignore to exclude docs/* but
explicitly include docs/openapi.json.

* Remove redundant zero initialization in server config

The config structure is calloc'd, so explicit initialization of
metrics_port and rest_http_port to 0 is unnecessary.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant