Commit c5c651e4 authored by jan.koester's avatar jan.koester
Browse files

Initial import of sharedd

parents
Loading
Loading
Loading
Loading

CMakeLists.txt

0 → 100644
+50 −0
Changes for CMakeLists.txt: 50 added lines, 0 removed lines.
Original line number Diff line number Diff line
cmake_minimum_required(VERSION 3.16)
project(sharedd VERSION 0.1.0 LANGUAGES CXX)

# sharedd: SMB and NFS shares served by the kernel's own file servers --
# ksmbd for SMB2/3 and knfsd for NFSv4. sharedd is what the kernel asks
# who may log in and which share means which directory (in place of
# ksmbd.mountd and rpc.mountd), keeps the shares in /etc/sharedd/sharedd.yaml
# (libconfplus) and offers them on sysbus as the service "sharedd".
# Users come from the libc: getpwnam(), getgrouplist(), getspnam() and,
# for SMB's NTLM, the NT hash shadow.yaml keeps next to the password
# (shadow_get_nthash(), set with shadow_set_password()). root never logs
# in over SMB.
#
#   sharedd    the daemon (root)
#   sharectl   command line over sysbus

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE RelWithDebInfo)
endif()

include(GNUInstallDirs)

find_package(libconfplus REQUIRED)
find_package(sysbus REQUIRED)

set(SHAREDD_CONFIG "/etc/sharedd/sharedd.yaml" CACHE FILEPATH "configuration file")

add_executable(sharedd
    src/main.cpp
    src/config.cpp
    src/smb.cpp
    src/nfs.cpp
    src/rpc.cpp
    src/files.cpp
)
target_include_directories(sharedd PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/src)
target_compile_definitions(sharedd PRIVATE SHAREDD_CONFIG="${SHAREDD_CONFIG}")
target_link_libraries(sharedd PRIVATE confplus::confplus sysbus::sysbus)

add_executable(sharectl src/sharectl.cpp)
target_include_directories(sharectl PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_link_libraries(sharectl PRIVATE sysbus::sysbus)

install(TARGETS sharedd sharectl RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR})
install(DIRECTORY include/sharedd DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(FILES dist/sharedd.yaml DESTINATION /etc/sharedd)
set(SHAREDD_UNITDIR "/etc/syslite/services" CACHE PATH "syslite unit directory")
install(FILES dist/sharedd.service DESTINATION ${SHAREDD_UNITDIR})

dist/sharedd.service

0 → 100644
+11 −0
Changes for dist/sharedd.service: 11 added lines, 0 removed lines.
Original line number Diff line number Diff line
[Unit]
Description=sharedd: SMB and NFS shares (kernel ksmbd/knfsd)
After=network.target

[Service]
Type=simple
ExecStart=/usr/sbin/sharedd
Restart=always

[Install]
WantedBy=multi-user.target

dist/sharedd.yaml

0 → 100644
+25 −0
Changes for dist/sharedd.yaml: 25 added lines, 0 removed lines.
Original line number Diff line number Diff line
# sharedd: SMB and NFS shares (served by the kernel's ksmbd and knfsd).
# Edit with sharectl or webctl; by hand, then: sharectl reload
sharedd:
  smb:
    enabled: true
    workgroup: WORKGROUP
    server_string: FenrirOS
    min_protocol: SMB2_10
    max_protocol: SMB3_11
    signing: auto
    map_to_guest: never       # bad_user: unknown users become the guest account
    guest_account: nobody
  nfs:
    enabled: true             # NFSv4 only (port 2049)
    threads: 8
    root: /                   # NFSv4 root, clients see it as "/" (not on overlayfs)
  # shares:
  #   - name: data
  #     path: /srv/data
  #     comment: Daten
  #     smb: true
  #     users: [jan, "@staff"]  # SMB; empty: every user with an SMB password
  #     nfs: true
  #     nfs_clients: ["192.168.1.0/24"]
  #     squash: root            # root|all|none

include/sharedd/api.h

0 → 100644
+100 −0
Changes for include/sharedd/api.h: 100 added lines, 0 removed lines.
Original line number Diff line number Diff line
/*******************************************************************************
Copyright (c) 2026, Jan Koester jan.koester@gmx.net
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the <organization> nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/

/* sharedd on sysbus: the service "sharedd", reached with
 * sysbus::Client::callService(sharedd::Service, method, fields).
 * Queries are open to everyone, changes need root (the bus passes the
 * caller's uid along). Error messages are in English, or in German if
 * the call has a field "lang" starting with "de".
 *
 * A share, in replies and as arguments:
 *   name        SMB share name; letters, digits, . _ - (max. 63)
 *   path        absolute directory; created if missing (see createShareDir()
 *               in src/config.h for owner and mode)
 *   comment     free text
 *   read_only   yes|no
 *   smb, nfs    yes|no: served over SMB / NFS
 *   guest       yes|no: SMB without a login (as the guest account)
 *   user        repeated: who may use it over SMB, "@group" for a group;
 *               none: every user with an SMB password
 *   client      repeated: who may mount it over NFS -- an address, an
 *               address/prefix or "*"
 *   squash      root|all|none: NFS uid mapping to the anonymous user
 *   async       yes|no: NFS async writes
 *   fsid        NFS filesystem id (0 or missing: derived from the path)
 * ListShares repeats these per share, each starting with its "name".
 *
 * Settings: smb (yes|no), workgroup, netbios_name, server_string,
 * min_protocol, max_protocol (SMB2_10 SMB3_00 SMB3_02 SMB3_11), signing
 * (disabled|enabled|auto|mandatory), map_to_guest (never|bad_user),
 * guest_account, nfs (yes|no), nfs_threads, nfs_root (the directory NFSv4
 * clients see as "/"; NFS shares have to be below it).
 *
 * Status: smb_state / nfs_state (disabled|running|failed), smb_error /
 * nfs_error, shares. */

#pragma once

namespace sharedd {

constexpr const char *Service = "sharedd";

namespace method {
constexpr const char *Status = "Status";
constexpr const char *ListShares = "ListShares";
constexpr const char *GetShare = "GetShare";            // name
constexpr const char *CreateShare = "CreateShare";      // a share
constexpr const char *EditShare = "EditShare";          // name + the whole new share (rename: new_name)
constexpr const char *DeleteShare = "DeleteShare";      // name
constexpr const char *GetSettings = "GetSettings";
constexpr const char *SetSettings = "SetSettings";      // the settings to change
constexpr const char *Reload = "Reload";                // re-read the configuration file

// Files and folders inside a share (root only). path: inside the share,
// "" for its own folder; ".." and symlinks can't lead out of it.
//   Browse {share, path} -> path, self_owner/self_group/self_mode (the
//     folder's own), then per entry: entry (its name), type
//     (dir|file|link|other), size, mtime, owner, group, uid, gid, mode
//     (octal, e.g. 2775)
//   SetPermissions {share, path, owner?, group?, mode? (octal, no setuid),
//     recursive?}: recursively, folders get the mode, files the mode
//     without execute bits
//   CreateFolder / CreateFile {share, path, name}: owner and group of the
//     folder they're made in (folders: also its setgid bit)
//   Delete {share, path, name}: folders with everything in them
constexpr const char *Browse = "Browse";
constexpr const char *SetPermissions = "SetPermissions";
constexpr const char *CreateFolder = "CreateFolder";
constexpr const char *CreateFile = "CreateFile";
constexpr const char *Delete = "Delete";
} // namespace method

namespace signal {
constexpr const char *SharesChanged = "SharesChanged";
} // namespace signal

} // namespace sharedd

src/config.cpp

0 → 100644
+442 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading