mirror of
https://codeberg.org/icewind/SMB.git
synced 2026-06-03 17:24:07 +02:00
Merge pull request 'ci' (#135) from forgejo-ci into master
Reviewed-on: https://codeberg.org/icewind/SMB/pulls/135
This commit is contained in:
commit
46cbd2cc8f
26 changed files with 252 additions and 159 deletions
1
.envrc
Normal file
1
.envrc
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
use flake
|
||||||
2
.envrc.license
Normal file
2
.envrc.license
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
SPDX-FileCopyrightText: 2014 Robin Appelman <robin@icewind.nl>
|
||||||
|
SPDX-License-Identifier: MIT
|
||||||
|
|
@ -1,41 +1,39 @@
|
||||||
# SPDX-FileCopyrightText: 2021 Robin Appelman <robin@icewind.nl>
|
# SPDX-FileCopyrightText: 2021 Robin Appelman <robin@icewind.nl>
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
on: [push, pull_request]
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- master
|
||||||
|
|
||||||
name: CI
|
name: CI
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
php-cs-fixer:
|
php-cs-fixer:
|
||||||
name: PHP-CS-Fixer
|
name: PHP-CS-Fixer
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- name: Setup PHP
|
- name: Setup PHP
|
||||||
uses: shivammathur/setup-php@v2
|
uses: https://github.com/shivammathur/setup-php@v2
|
||||||
with:
|
with:
|
||||||
php-version: '8.0'
|
php-version: '8.2'
|
||||||
extensions: apcu
|
extensions: apcu
|
||||||
|
- name: Composer
|
||||||
|
run: composer install
|
||||||
- name: PHP-CS-Fixer
|
- name: PHP-CS-Fixer
|
||||||
uses: OskarStark/php-cs-fixer-ga@2.16.7
|
run: |
|
||||||
with:
|
composer run cs:check
|
||||||
args: --diff --dry-run --allow-risky yes --stop-on-violation --using-cache=no --path-mode=intersection
|
|
||||||
|
|
||||||
php-versions:
|
php-versions:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
name: Unit tests
|
name: Unit tests - PHP ${{ matrix.php-version }}
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
backend:
|
|
||||||
- smbclient
|
|
||||||
- libsmbclient
|
|
||||||
php-version:
|
php-version:
|
||||||
- "7.2"
|
|
||||||
- "7.3"
|
|
||||||
- "7.4"
|
|
||||||
- "8.0"
|
|
||||||
- "8.1"
|
|
||||||
- "8.2"
|
- "8.2"
|
||||||
- "8.3"
|
- "8.3"
|
||||||
- "8.4"
|
- "8.4"
|
||||||
|
|
@ -47,17 +45,17 @@ jobs:
|
||||||
ACCOUNT_test: test
|
ACCOUNT_test: test
|
||||||
UID_test: 1000
|
UID_test: 1000
|
||||||
SAMBA_VOLUME_CONFIG_test: "[test]; path=/tmp; valid users = test; guest ok = no; read only = no; browseable = yes"
|
SAMBA_VOLUME_CONFIG_test: "[test]; path=/tmp; valid users = test; guest ok = no; read only = no; browseable = yes"
|
||||||
ports:
|
|
||||||
- 139:139
|
|
||||||
- 445:445
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Install packages
|
- name: Install packages
|
||||||
|
env:
|
||||||
|
DEBIAN_FRONTEND: noninteractive
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get install smbclient libsmbclient-dev
|
sudo apt-get update
|
||||||
- uses: actions/checkout@v3
|
sudo apt-get install -y smbclient libsmbclient-dev
|
||||||
|
- uses: actions/checkout@v4
|
||||||
- name: Setup PHP
|
- name: Setup PHP
|
||||||
uses: shivammathur/setup-php@v2
|
uses: https://github.com/shivammathur/setup-php@v2
|
||||||
with:
|
with:
|
||||||
php-version: "${{ matrix.php-version }}"
|
php-version: "${{ matrix.php-version }}"
|
||||||
extensions: apcu, smbclient
|
extensions: apcu, smbclient
|
||||||
|
|
@ -66,23 +64,32 @@ jobs:
|
||||||
run: composer install
|
run: composer install
|
||||||
- name: Config
|
- name: Config
|
||||||
run: |
|
run: |
|
||||||
echo '{"host": "localhost","user": "test","password": "test","share": "test","root": ""}' > tests/config.json
|
echo '{"host": "samba","user": "test","password": "test","share": "test","root": ""}' > tests/config.json
|
||||||
- name: PHPUnit Tests
|
- name: PHPUnit Tests - smbclient
|
||||||
uses: nick-invision/retry@v2
|
uses: https://github.com/nick-invision/retry@v2
|
||||||
with:
|
with:
|
||||||
timeout_minutes: 2
|
timeout_minutes: 2
|
||||||
max_attempts: 3
|
max_attempts: 3
|
||||||
retry_on: timeout
|
retry_on: timeout
|
||||||
command: php ./vendor/bin/phpunit tests -c tests/phpunit.xml --coverage-clover=coverage.xml
|
command: php ./vendor/bin/phpunit tests -c tests/phpunit.xml --coverage-clover=coverage.xml
|
||||||
env:
|
env:
|
||||||
BACKEND: ${{ matrix.backend }}
|
BACKEND: smbclient
|
||||||
- uses: codecov/codecov-action@v3
|
- name: PHPUnit Tests - libsmbclient
|
||||||
|
uses: https://github.com/nick-invision/retry@v2
|
||||||
|
with:
|
||||||
|
timeout_minutes: 2
|
||||||
|
max_attempts: 3
|
||||||
|
retry_on: timeout
|
||||||
|
command: php ./vendor/bin/phpunit tests -c tests/phpunit.xml --coverage-clover=coverage.xml
|
||||||
|
env:
|
||||||
|
BACKEND: libsmbclient
|
||||||
|
- uses: https://github.com/codecov/codecov-action@v3
|
||||||
with:
|
with:
|
||||||
files: ./coverage.xml
|
files: ./coverage.xml
|
||||||
|
|
||||||
smb-versions:
|
smb-versions:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
name: Unit tests
|
name: Unit tests - Samba ${{ matrix.server-version }} - smbclient ${{ matrix.client-version }}
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
|
|
@ -109,32 +116,32 @@ jobs:
|
||||||
ACCOUNT_test: test
|
ACCOUNT_test: test
|
||||||
UID_test: 1000
|
UID_test: 1000
|
||||||
SAMBA_VOLUME_CONFIG_test: "[test]; path=/tmp; valid users = test; guest ok = no; read only = no; browseable = yes"
|
SAMBA_VOLUME_CONFIG_test: "[test]; path=/tmp; valid users = test; guest ok = no; read only = no; browseable = yes"
|
||||||
ports:
|
|
||||||
- 139:139
|
|
||||||
- 445:445
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Setup smbclient
|
- name: Setup smbclient
|
||||||
|
env:
|
||||||
|
DEBIAN_FRONTEND: noninteractive
|
||||||
run: |
|
run: |
|
||||||
sudo apt install libjansson4 libcap2 libbsd0 libreadline8 libicu70
|
sudo apt-get update
|
||||||
|
sudo apt install -y libjansson4 libcap2 libbsd0 libreadline8 libicu70
|
||||||
sudo mkdir -p /etc/samba /var/lib/samba/private
|
sudo mkdir -p /etc/samba /var/lib/samba/private
|
||||||
echo "[global]\nclient min protocol = SMB2\nclient max protocol = SMB3" | sudo tee /etc/samba/smb.conf
|
echo "[global]\nclient min protocol = SMB2\nclient max protocol = SMB3" | sudo tee /etc/samba/smb.conf
|
||||||
sudo wget "https://github.com/icewind1991/smbclient-builder/releases/download/v0.2.0/smbclient-${{ matrix.client-version }}" -O /usr/local/bin/smbclient
|
sudo wget "https://github.com/icewind1991/smbclient-builder/releases/download/v0.2.0/smbclient-${{ matrix.client-version }}" -O /usr/local/bin/smbclient
|
||||||
sudo chmod +x /usr/local/bin/smbclient
|
sudo chmod +x /usr/local/bin/smbclient
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- name: Setup PHP
|
- name: Setup PHP
|
||||||
uses: shivammathur/setup-php@v2
|
uses: https://github.com/shivammathur/setup-php@v2
|
||||||
with:
|
with:
|
||||||
php-version: 8.0
|
php-version: 8.2
|
||||||
extensions: apcu, smbclient
|
extensions: apcu, smbclient
|
||||||
coverage: pcov
|
coverage: pcov
|
||||||
- name: Composer
|
- name: Composer
|
||||||
run: composer install
|
run: composer install
|
||||||
- name: Config
|
- name: Config
|
||||||
run: |
|
run: |
|
||||||
echo '{"host": "localhost","user": "test","password": "test","share": "test","root": ""}' > tests/config.json
|
echo '{"host": "samba","user": "test","password": "test","share": "test","root": ""}' > tests/config.json
|
||||||
- name: PHPUnit Tests
|
- name: PHPUnit Tests
|
||||||
uses: nick-invision/retry@v2
|
uses: https://github.com/nick-invision/retry@v2
|
||||||
with:
|
with:
|
||||||
timeout_minutes: 2
|
timeout_minutes: 2
|
||||||
max_attempts: 3
|
max_attempts: 3
|
||||||
|
|
@ -142,12 +149,12 @@ jobs:
|
||||||
command: php ./vendor/bin/phpunit tests -c tests/phpunit.xml --coverage-clover=coverage.xml
|
command: php ./vendor/bin/phpunit tests -c tests/phpunit.xml --coverage-clover=coverage.xml
|
||||||
env:
|
env:
|
||||||
BACKEND: smbclient
|
BACKEND: smbclient
|
||||||
- uses: codecov/codecov-action@v3
|
- uses: https://github.com/codecov/codecov-action@v3
|
||||||
with:
|
with:
|
||||||
files: ./coverage.xml
|
files: ./coverage.xml
|
||||||
|
|
||||||
alpine-test:
|
alpine-test:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: alpine-latest
|
||||||
name: Unit tests (alpine)
|
name: Unit tests (alpine)
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
|
@ -157,83 +164,51 @@ jobs:
|
||||||
ACCOUNT_test: test
|
ACCOUNT_test: test
|
||||||
UID_test: 1000
|
UID_test: 1000
|
||||||
SAMBA_VOLUME_CONFIG_test: "[test]; path=/tmp; valid users = test; guest ok = no; read only = no; browseable = yes"
|
SAMBA_VOLUME_CONFIG_test: "[test]; path=/tmp; valid users = test; guest ok = no; read only = no; browseable = yes"
|
||||||
ports:
|
|
||||||
- 139:139
|
|
||||||
- 445:445
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- name: Setup PHP
|
- name: Install dependencies
|
||||||
uses: shivammathur/setup-php@v2
|
shell: sh
|
||||||
with:
|
run: |
|
||||||
php-version: 8.0
|
apk add bash sudo git coreutils samba-client php composer php-curl php-iconv php-mbstring php-openssl php-zip php-phar php-tokenizer php-dom php-xml php-xmlwriter
|
||||||
- name: Composer
|
- name: Composer
|
||||||
run: composer install
|
run: composer install
|
||||||
- name: Pull images
|
|
||||||
run: |
|
|
||||||
docker pull icewind1991/smbclient-php-alpine
|
|
||||||
- name: Config
|
- name: Config
|
||||||
run: |
|
run: |
|
||||||
echo '{"host": "localhost","user": "test","password": "test","share": "test","root": ""}' > tests/config.json
|
echo '{"host": "samba","user": "test","password": "test","share": "test","root": ""}' > tests/config.json
|
||||||
- name: PHPUnit Tests
|
- name: PHPUnit Tests - smbclient
|
||||||
run: |
|
uses: https://github.com/nick-invision/retry@v2
|
||||||
docker run --network "host" --rm -v $PWD:/smb icewind1991/smbclient-php-alpine /smb/vendor/bin/phpunit -c /smb/tests/phpunit.xml /smb/tests
|
|
||||||
|
|
||||||
kerberos-sso:
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
name: Kerberos SSO tests
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Setup PHP
|
|
||||||
uses: shivammathur/setup-php@v2
|
|
||||||
with:
|
with:
|
||||||
php-version: 8.0
|
timeout_minutes: 2
|
||||||
- name: Composer
|
max_attempts: 3
|
||||||
run: composer install
|
retry_on: timeout
|
||||||
- name: Pull images
|
command: php ./vendor/bin/phpunit tests -c tests/phpunit.xml --coverage-clover=coverage.xml
|
||||||
run: |
|
env:
|
||||||
docker pull icewind1991/samba-krb-test-dc
|
BACKEND: smbclient
|
||||||
docker pull icewind1991/samba-krb-test-apache
|
|
||||||
docker pull icewind1991/samba-krb-test-client
|
|
||||||
- name: Setup AD-DC
|
|
||||||
run: |
|
|
||||||
tests/setup-krb.sh
|
|
||||||
- name: Test kerberos auth
|
|
||||||
run: |
|
|
||||||
DC_IP=$(docker inspect dc --format '{{.NetworkSettings.IPAddress}}')
|
|
||||||
LIST=$(docker run --rm --name client -v /tmp/shared:/shared --dns $DC_IP --hostname client.domain.test icewind1991/samba-krb-test-client \
|
|
||||||
curl -s --negotiate -u testuser@DOMAIN.TEST: --delegation always http://httpd.domain.test/example-sso-kerberos.php)
|
|
||||||
echo $LIST
|
|
||||||
LIST=$(echo $LIST | tr -d '[:space:]')
|
|
||||||
[[ $LIST == "test.txt" ]]
|
|
||||||
- name: Apache logs
|
|
||||||
if: always()
|
|
||||||
run: |
|
|
||||||
docker logs apache
|
|
||||||
|
|
||||||
static-psalm-analysis:
|
static-psalm-analysis:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-latest
|
||||||
name: Psalm static analysis
|
name: Psalm static analysis - PHP ${{ matrix.php-version }}
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
php-version:
|
php-version:
|
||||||
- "7.2"
|
|
||||||
- "7.3"
|
|
||||||
- "7.4"
|
|
||||||
- "8.0"
|
|
||||||
- "8.1"
|
|
||||||
- "8.2"
|
- "8.2"
|
||||||
- "8.3"
|
- "8.3"
|
||||||
|
- "8.4"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: krb5-dev
|
- name: krb5-dev
|
||||||
run: sudo apt-get install -y libkrb5-dev libsmbclient-dev
|
env:
|
||||||
|
DEBIAN_FRONTEND: noninteractive
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y libkrb5-dev libsmbclient-dev
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
- name: Set up php
|
- name: Set up php
|
||||||
uses: shivammathur/setup-php@master
|
uses: https://github.com/shivammathur/setup-php@master
|
||||||
with:
|
with:
|
||||||
php-version: "${{ matrix.php-version }}"
|
php-version: "${{ matrix.php-version }}"
|
||||||
tools: composer:v2
|
tools: composer:v2
|
||||||
|
|
@ -248,16 +223,18 @@ jobs:
|
||||||
|
|
||||||
phpstan:
|
phpstan:
|
||||||
name: PHPStan Static Analysis
|
name: PHPStan Static Analysis
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: krb5-dev
|
- name: krb5-dev
|
||||||
run: sudo apt-get install -y libkrb5-dev
|
run: |
|
||||||
- uses: actions/checkout@v3
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y libkrb5-dev
|
||||||
|
- uses: actions/checkout@v4
|
||||||
- name: Setup PHP
|
- name: Setup PHP
|
||||||
uses: shivammathur/setup-php@v2
|
uses: https://github.com/shivammathur/setup-php@v2
|
||||||
with:
|
with:
|
||||||
php-version: '8.0'
|
php-version: 8.3
|
||||||
extensions: apcu, smbclient, krb5
|
extensions: apcu, smbclient, krb5
|
||||||
env:
|
env:
|
||||||
fail-fast: true
|
fail-fast: true
|
||||||
|
|
@ -10,6 +10,6 @@ jobs:
|
||||||
reuse-compliance-check:
|
reuse-compliance-check:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
- uses: https://github.com/actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
||||||
- name: REUSE Compliance Check
|
- name: REUSE Compliance Check
|
||||||
uses: fsfe/reuse-action@a46482ca367aef4454a87620aa37c2be4b2f8106 # v3.0.0
|
uses: https://github.com/fsfe/reuse-action@a46482ca367aef4454a87620aa37c2be4b2f8106 # v3.0.0
|
||||||
|
|
@ -9,13 +9,16 @@ $finder = PhpCsFixer\Finder::create()
|
||||||
->exclude('vendor')
|
->exclude('vendor')
|
||||||
->in(__DIR__)
|
->in(__DIR__)
|
||||||
;
|
;
|
||||||
return PhpCsFixer\Config::create()
|
return (new PhpCsFixer\Config())
|
||||||
->setRules([
|
->setRules([
|
||||||
'@PSR2' => true,
|
'@PSR2' => true,
|
||||||
|
'curly_braces_position' => [
|
||||||
|
'classes_opening_brace' => 'same_line',
|
||||||
|
'functions_opening_brace' => 'same_line',
|
||||||
|
],
|
||||||
'array_syntax' => ['syntax' => 'short'],
|
'array_syntax' => ['syntax' => 'short'],
|
||||||
'braces' => ['position_after_functions_and_oop_constructs' => 'same'],
|
'braces' => ['position_after_functions_and_oop_constructs' => 'same'],
|
||||||
'binary_operator_spaces' => ['align_double_arrow' => true, 'align_equals' => false],
|
'binary_operator_spaces' => ['operators' => ['=>' => 'align_single_space']],
|
||||||
])
|
])
|
||||||
->setIndent("\t")
|
->setIndent("\t")
|
||||||
->setFinder($finder)
|
->setFinder($finder);
|
||||||
;
|
|
||||||
|
|
@ -9,14 +9,14 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=7.2",
|
"php": ">=8.2",
|
||||||
"icewind/streams": ">=0.7.3"
|
"icewind/streams": ">=0.7.3"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^8.5|^9.3.8",
|
"phpunit/phpunit": "^8.5|^9.3.8",
|
||||||
"friendsofphp/php-cs-fixer": "^2.16",
|
"friendsofphp/php-cs-fixer": "v3.89.0",
|
||||||
"phpstan/phpstan": "^0.12.57",
|
"phpstan/phpstan": "^0.12.57",
|
||||||
"psalm/phar": "^4.3"
|
"psalm/phar": "6.*"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
|
|
|
||||||
47
flake.lock
generated
Normal file
47
flake.lock
generated
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"flakelight": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1751892651,
|
||||||
|
"narHash": "sha256-oLNt26YpwTVj+t7BunpmL+iOUHVt5VLvYB1vnJ7Kw28=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "flakelight",
|
||||||
|
"rev": "f4604c27e117ad54391160ae207b519694b9f845",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "flakelight",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1751741127,
|
||||||
|
"narHash": "sha256-t75Shs76NgxjZSgvvZZ9qOmz5zuBE8buUaYD28BMTxg=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "29e290002bfff26af1db6f64d070698019460302",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"id": "nixpkgs",
|
||||||
|
"ref": "nixos-25.05",
|
||||||
|
"type": "indirect"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"flakelight": "flakelight",
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
2
flake.lock.license
Normal file
2
flake.lock.license
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
SPDX-FileCopyrightText: 2014 Robin Appelman <robin@icewind.nl>
|
||||||
|
SPDX-License-Identifier: MIT
|
||||||
34
flake.nix
Normal file
34
flake.nix
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "nixpkgs/nixos-25.05";
|
||||||
|
flakelight = {
|
||||||
|
url = "github:nix-community/flakelight";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
outputs = {flakelight, ...}:
|
||||||
|
flakelight ./. {
|
||||||
|
formatters = pkgs: {
|
||||||
|
"*.php" = pkgs.lib.getExe pkgs.php84.packages.php-cs-fixer;
|
||||||
|
};
|
||||||
|
devShell.packages = pkgs: let
|
||||||
|
php_version = "81";
|
||||||
|
php = pkgs.pkgs."php${php_version}".buildEnv {
|
||||||
|
extensions = {
|
||||||
|
enabled,
|
||||||
|
all,
|
||||||
|
}:
|
||||||
|
enabled
|
||||||
|
++ (with all; [
|
||||||
|
dom
|
||||||
|
simplexml
|
||||||
|
tokenizer
|
||||||
|
filter
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
in [
|
||||||
|
php.packages.composer
|
||||||
|
php
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
2
flake.nix.license
Normal file
2
flake.nix.license
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
SPDX-FileCopyrightText: 2014 Robin Appelman <robin@icewind.nl>
|
||||||
|
SPDX-License-Identifier: MIT
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xmlns="https://getpsalm.org/schema/config"
|
xmlns="https://getpsalm.org/schema/config"
|
||||||
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
||||||
|
findUnusedCode="false"
|
||||||
>
|
>
|
||||||
<stubs>
|
<stubs>
|
||||||
<file name="tests/krb.phpstub" preloadClasses="true"/>
|
<file name="tests/krb.phpstub" preloadClasses="true"/>
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ class BasicAuth implements IAuth {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getExtraCommandLineArguments(): string {
|
public function getExtraCommandLineArguments(): string {
|
||||||
return ($this->workgroup) ? '-W ' . escapeshellarg($this->workgroup) : '';
|
return ($this->workgroup !== null) ? '-W ' . escapeshellarg($this->workgroup) : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setExtraSmbClientOptions($smbClientState): void {
|
public function setExtraSmbClientOptions($smbClientState): void {
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ class Exception extends \Exception {
|
||||||
*/
|
*/
|
||||||
public static function unknown(?string $path, $error): Exception {
|
public static function unknown(?string $path, $error): Exception {
|
||||||
$message = 'Unknown error (' . (string)$error . ')';
|
$message = 'Unknown error (' . (string)$error . ')';
|
||||||
if ($path) {
|
if ($path !== null) {
|
||||||
$message .= ' for ' . $path;
|
$message .= ' for ' . $path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,9 @@ class InvalidRequestException extends Exception {
|
||||||
*/
|
*/
|
||||||
protected $path;
|
protected $path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @psalm-suppress ParamNameMismatch
|
||||||
|
*/
|
||||||
public function __construct(string $path = "", int $code = 0, ?\Throwable $previous = null) {
|
public function __construct(string $path = "", int $code = 0, ?\Throwable $previous = null) {
|
||||||
$class = get_class($this);
|
$class = get_class($this);
|
||||||
$parts = explode('\\', $class);
|
$parts = explode('\\', $class);
|
||||||
|
|
|
||||||
|
|
@ -9,5 +9,4 @@ declare(strict_types=1);
|
||||||
namespace Icewind\SMB\Exception;
|
namespace Icewind\SMB\Exception;
|
||||||
|
|
||||||
class InvalidTicket extends Exception {
|
class InvalidTicket extends Exception {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -26,7 +26,7 @@ class KerberosTicket {
|
||||||
return $this->cacheName;
|
return $this->cacheName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName(): string{
|
public function getName(): string {
|
||||||
return $this->krb5->getName();
|
return $this->krb5->getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,7 +47,7 @@ class KerberosTicket {
|
||||||
*/
|
*/
|
||||||
public static function fromEnv(): ?KerberosTicket {
|
public static function fromEnv(): ?KerberosTicket {
|
||||||
$ticketName = getenv("KRB5CCNAME");
|
$ticketName = getenv("KRB5CCNAME");
|
||||||
if (!$ticketName) {
|
if ($ticketName === false) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
$krb5 = new KRB5CCache();
|
$krb5 = new KRB5CCache();
|
||||||
|
|
|
||||||
|
|
@ -129,9 +129,17 @@ class NativeFileInfo implements IFileInfo {
|
||||||
$attribute = $this->share->getAttribute($this->path, 'system.nt_sec_desc.acl.*+');
|
$attribute = $this->share->getAttribute($this->path, 'system.nt_sec_desc.acl.*+');
|
||||||
|
|
||||||
foreach (explode(',', $attribute) as $acl) {
|
foreach (explode(',', $attribute) as $acl) {
|
||||||
list($user, $permissions) = explode(':', $acl, 2);
|
$parts = explode(':', $acl, 2);
|
||||||
|
if (count($parts) !== 2) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
list($user, $permissions) = $parts;
|
||||||
$user = trim($user, '\\');
|
$user = trim($user, '\\');
|
||||||
list($type, $flags, $mask) = explode('/', $permissions);
|
$parts = explode('/', $permissions);
|
||||||
|
if (count($parts) < 3) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
list($type, $flags, $mask) = $parts;
|
||||||
$mask = hexdec($mask);
|
$mask = hexdec($mask);
|
||||||
|
|
||||||
$acls[$user] = new ACL((int)$type, (int)$flags, (int)$mask);
|
$acls[$user] = new ACL((int)$type, (int)$flags, (int)$mask);
|
||||||
|
|
|
||||||
|
|
@ -322,7 +322,7 @@ class NativeState {
|
||||||
if (!$this->state) {
|
if (!$this->state) {
|
||||||
throw new ConnectionException("Not connected");
|
throw new ConnectionException("Not connected");
|
||||||
}
|
}
|
||||||
if ($length) {
|
if ($length !== null) {
|
||||||
$result = @smbclient_write($this->state, $file, $data, $length);
|
$result = @smbclient_write($this->state, $file, $data, $length);
|
||||||
} else {
|
} else {
|
||||||
$result = @smbclient_write($this->state, $file, $data);
|
$result = @smbclient_write($this->state, $file, $data);
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ class TimeZoneProvider implements ITimeZoneProvider {
|
||||||
$timeZone = null;
|
$timeZone = null;
|
||||||
$net = $this->system->getNetPath();
|
$net = $this->system->getNetPath();
|
||||||
// for local domain names we can assume same timezone
|
// for local domain names we can assume same timezone
|
||||||
if ($net && $host && strpos($host, '.') !== false) {
|
if ($net !== null && $host && strpos($host, '.') !== false) {
|
||||||
$command = sprintf(
|
$command = sprintf(
|
||||||
'%s time zone -S %s',
|
'%s time zone -S %s',
|
||||||
$net,
|
$net,
|
||||||
|
|
@ -37,11 +37,12 @@ class TimeZoneProvider implements ITimeZoneProvider {
|
||||||
$timeZone = exec($command);
|
$timeZone = exec($command);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$timeZone) {
|
if (!is_string($timeZone)) {
|
||||||
$date = $this->system->getDatePath();
|
$date = $this->system->getDatePath();
|
||||||
if ($date) {
|
if ($date !== null) {
|
||||||
$timeZone = exec($date . " +%z");
|
$timeZone = exec($date . " +%z");
|
||||||
} else {
|
}
|
||||||
|
if (!is_string($timeZone)) {
|
||||||
$timeZone = date_default_timezone_get();
|
$timeZone = date_default_timezone_get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,11 +93,11 @@ class Connection extends RawConnection {
|
||||||
* @return no-return
|
* @return no-return
|
||||||
*/
|
*/
|
||||||
private function unknownError($promptLine = '') {
|
private function unknownError($promptLine = '') {
|
||||||
if ($promptLine) { //maybe we have some error we missed on the previous line
|
if ($promptLine !== false) { //maybe we have some error we missed on the previous line
|
||||||
throw new ConnectException('Unknown error (' . $promptLine . ')');
|
throw new ConnectException('Unknown error (' . $promptLine . ')');
|
||||||
} else {
|
} else {
|
||||||
$error = $this->readError(); // maybe something on stderr
|
$error = $this->readError(); // maybe something on stderr
|
||||||
if ($error) {
|
if ($error !== false) {
|
||||||
throw new ConnectException('Unknown error (stderr: ' . $error . ')');
|
throw new ConnectException('Unknown error (stderr: ' . $error . ')');
|
||||||
} else {
|
} else {
|
||||||
throw new ConnectException('Unknown error');
|
throw new ConnectException('Unknown error');
|
||||||
|
|
|
||||||
|
|
@ -78,14 +78,17 @@ class Parser {
|
||||||
* @throws NotFoundException
|
* @throws NotFoundException
|
||||||
*/
|
*/
|
||||||
public function checkForError(array $output, string $path): void {
|
public function checkForError(array $output, string $path): void {
|
||||||
if (strpos($output[0], 'does not exist')) {
|
$error = '';
|
||||||
throw new NotFoundException($path);
|
if (isset($output[0])) {
|
||||||
}
|
if (strpos($output[0], 'does not exist') > 0) {
|
||||||
$error = $this->getErrorCode($output[0]);
|
throw new NotFoundException($path);
|
||||||
|
}
|
||||||
|
$error = $this->getErrorCode($output[0]);
|
||||||
|
|
||||||
if (substr($output[0], 0, strlen(self::MSG_NOT_FOUND)) === self::MSG_NOT_FOUND) {
|
if (substr($output[0], 0, strlen(self::MSG_NOT_FOUND)) === self::MSG_NOT_FOUND) {
|
||||||
$localPath = substr($output[0], strlen(self::MSG_NOT_FOUND));
|
$localPath = substr($output[0], strlen(self::MSG_NOT_FOUND));
|
||||||
throw new InvalidResourceException('Failed opening local file "' . $localPath . '" for writing');
|
throw new InvalidResourceException('Failed opening local file "' . $localPath . '" for writing');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw Exception::fromMap(self::EXCEPTION_MAP, $error, $path);
|
throw Exception::fromMap(self::EXCEPTION_MAP, $error, $path);
|
||||||
|
|
@ -197,12 +200,12 @@ class Parser {
|
||||||
public function parseListShares(array $output): array {
|
public function parseListShares(array $output): array {
|
||||||
$shareNames = [];
|
$shareNames = [];
|
||||||
foreach ($output as $line) {
|
foreach ($output as $line) {
|
||||||
if (strpos($line, '|')) {
|
if (strpos($line, '|') > 0) {
|
||||||
list($type, $name, $description) = explode('|', $line);
|
list($type, $name, $description) = explode('|', $line);
|
||||||
if (strtolower($type) === 'disk') {
|
if (strtolower($type) === 'disk') {
|
||||||
$shareNames[$name] = $description;
|
$shareNames[$name] = $description;
|
||||||
}
|
}
|
||||||
} elseif (strpos($line, 'Disk')) {
|
} elseif (strpos($line, 'Disk') > 0) {
|
||||||
// new output format
|
// new output format
|
||||||
list($name, $description) = explode('Disk', $line);
|
list($name, $description) = explode('Disk', $line);
|
||||||
$shareNames[trim($name)] = trim($description);
|
$shareNames[trim($name)] = trim($description);
|
||||||
|
|
@ -221,12 +224,24 @@ class Parser {
|
||||||
if (strpos($acl, ':') === false) {
|
if (strpos($acl, ':') === false) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
[$type, $acl] = explode(':', $acl, 2);
|
$parts = explode(':', $acl, 2);
|
||||||
|
if (count($parts) !== 2) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
[$type, $acl] = $parts;
|
||||||
if ($type !== 'ACL') {
|
if ($type !== 'ACL') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
[$user, $permissions] = explode(':', $acl, 2);
|
$parts = explode(':', $acl, 2);
|
||||||
[$type, $flags, $mask] = explode('/', $permissions);
|
if (count($parts) !== 2) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
[$user, $permissions] = $parts;
|
||||||
|
$parts = explode('/', $permissions);
|
||||||
|
if (count($parts) < 3) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
[$type, $flags, $mask] = $parts;
|
||||||
|
|
||||||
$type = $type === 'ALLOWED' ? ACL::TYPE_ALLOW : ACL::TYPE_DENY;
|
$type = $type === 'ALLOWED' ? ACL::TYPE_ALLOW : ACL::TYPE_DENY;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ class Server extends AbstractServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getAuthFileArgument(): string {
|
private function getAuthFileArgument(): string {
|
||||||
if ($this->getAuth()->getUsername()) {
|
if ($this->getAuth()->getUsername() !== null) {
|
||||||
return '--authentication-file=' . $this->system->getFD(3);
|
return '--authentication-file=' . $this->system->getFD(3);
|
||||||
} else {
|
} else {
|
||||||
return '';
|
return '';
|
||||||
|
|
@ -54,8 +54,8 @@ class Server extends AbstractServer {
|
||||||
$smbClient,
|
$smbClient,
|
||||||
$this->getAuthFileArgument(),
|
$this->getAuthFileArgument(),
|
||||||
$this->getAuth()->getExtraCommandLineArguments(),
|
$this->getAuth()->getExtraCommandLineArguments(),
|
||||||
$maxProtocol ? "--option='client max protocol=" . $maxProtocol . "'" : "",
|
($maxProtocol !== null) ? "--option='client max protocol=" . $maxProtocol . "'" : "",
|
||||||
$minProtocol ? "--option='client min protocol=" . $minProtocol . "'" : "",
|
($minProtocol !== null) ? "--option='client min protocol=" . $minProtocol . "'" : "",
|
||||||
escapeshellarg('//' . $this->getHost())
|
escapeshellarg('//' . $this->getHost())
|
||||||
);
|
);
|
||||||
$connection = new RawConnection($command);
|
$connection = new RawConnection($command);
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ class Share extends AbstractShare {
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getAuthFileArgument(): string {
|
private function getAuthFileArgument(): string {
|
||||||
if ($this->server->getAuth()->getUsername()) {
|
if ($this->server->getAuth()->getUsername() !== null) {
|
||||||
return '--authentication-file=' . $this->system->getFD(3);
|
return '--authentication-file=' . $this->system->getFD(3);
|
||||||
} else {
|
} else {
|
||||||
return '';
|
return '';
|
||||||
|
|
@ -94,13 +94,13 @@ class Share extends AbstractShare {
|
||||||
$command = sprintf(
|
$command = sprintf(
|
||||||
'%s %s%s -t %s %s %s %s %s %s',
|
'%s %s%s -t %s %s %s %s %s %s',
|
||||||
self::EXEC_CMD,
|
self::EXEC_CMD,
|
||||||
$stdBuf ? $stdBuf . ' -o0 ' : '',
|
($stdBuf !== null) ? $stdBuf . ' -o0 ' : '',
|
||||||
$smbClient,
|
$smbClient,
|
||||||
$this->server->getOptions()->getTimeout(),
|
$this->server->getOptions()->getTimeout(),
|
||||||
$this->getAuthFileArgument(),
|
$this->getAuthFileArgument(),
|
||||||
$this->server->getAuth()->getExtraCommandLineArguments(),
|
$this->server->getAuth()->getExtraCommandLineArguments(),
|
||||||
$maxProtocol ? "--option='client max protocol=" . $maxProtocol . "'" : "",
|
($maxProtocol !== null) ? "--option='client max protocol=" . $maxProtocol . "'" : "",
|
||||||
$minProtocol ? "--option='client min protocol=" . $minProtocol . "'" : "",
|
($minProtocol !== null) ? "--option='client min protocol=" . $minProtocol . "'" : "",
|
||||||
escapeshellarg('//' . $this->server->getHost() . '/' . $this->name)
|
escapeshellarg('//' . $this->server->getHost() . '/' . $this->name)
|
||||||
);
|
);
|
||||||
$connection = new Connection($command, $this->parser);
|
$connection = new Connection($command, $this->parser);
|
||||||
|
|
@ -349,7 +349,7 @@ class Share extends AbstractShare {
|
||||||
$connection->write('get ' . $source . ' ' . $this->system->getFD(5));
|
$connection->write('get ' . $source . ' ' . $this->system->getFD(5));
|
||||||
$connection->write('exit');
|
$connection->write('exit');
|
||||||
$fh = $connection->getFileOutputStream();
|
$fh = $connection->getFileOutputStream();
|
||||||
$fh = CallbackWrapper::wrap($fh, function() use ($connection) {
|
$fh = CallbackWrapper::wrap($fh, function () use ($connection) {
|
||||||
$connection->write('');
|
$connection->write('');
|
||||||
});
|
});
|
||||||
if (!is_resource($fh)) {
|
if (!is_resource($fh)) {
|
||||||
|
|
@ -379,7 +379,7 @@ class Share extends AbstractShare {
|
||||||
|
|
||||||
// use a close callback to ensure the upload is finished before continuing
|
// use a close callback to ensure the upload is finished before continuing
|
||||||
// this also serves as a way to keep the connection in scope
|
// this also serves as a way to keep the connection in scope
|
||||||
$stream = CallbackWrapper::wrap($fh, function() use ($connection) {
|
$stream = CallbackWrapper::wrap($fh, function () use ($connection) {
|
||||||
$connection->write('');
|
$connection->write('');
|
||||||
}, null, function () use ($connection) {
|
}, null, function () use ($connection) {
|
||||||
$connection->close(false); // dont terminate, give the upload some time
|
$connection->close(false); // dont terminate, give the upload some time
|
||||||
|
|
@ -439,7 +439,7 @@ class Share extends AbstractShare {
|
||||||
* @throws DependencyException
|
* @throws DependencyException
|
||||||
*/
|
*/
|
||||||
public function notify(string $path): INotifyHandler {
|
public function notify(string $path): INotifyHandler {
|
||||||
if (!$this->system->getStdBufPath()) { //stdbuf is required to disable smbclient's output buffering
|
if ($this->system->getStdBufPath() == null) { //stdbuf is required to disable smbclient's output buffering
|
||||||
throw new DependencyException('stdbuf is required for usage of the notify command');
|
throw new DependencyException('stdbuf is required for usage of the notify command');
|
||||||
}
|
}
|
||||||
$connection = $this->getConnection(); // use a fresh connection since the notify command blocks the process
|
$connection = $this->getConnection(); // use a fresh connection since the notify command blocks the process
|
||||||
|
|
@ -519,7 +519,7 @@ class Share extends AbstractShare {
|
||||||
*/
|
*/
|
||||||
protected function getAcls(string $path): array {
|
protected function getAcls(string $path): array {
|
||||||
$commandPath = $this->system->getSmbcAclsPath();
|
$commandPath = $this->system->getSmbcAclsPath();
|
||||||
if (!$commandPath) {
|
if ($commandPath === null) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,8 +48,6 @@ abstract class AbstractShareTest extends TestCase {
|
||||||
abstract public function getServerClass(): string;
|
abstract public function getServerClass(): string;
|
||||||
|
|
||||||
public function setUp(): void {
|
public function setUp(): void {
|
||||||
// ob_end_flush();
|
|
||||||
// var_dump($this->getName());
|
|
||||||
$this->config = json_decode(file_get_contents(__DIR__ . '/config.json'));
|
$this->config = json_decode(file_get_contents(__DIR__ . '/config.json'));
|
||||||
$options = new Options();
|
$options = new Options();
|
||||||
$options->setMinProtocol(IOptions::PROTOCOL_SMB2);
|
$options->setMinProtocol(IOptions::PROTOCOL_SMB2);
|
||||||
|
|
|
||||||
|
|
@ -24,14 +24,14 @@ function waitContainer {
|
||||||
mkdir /tmp/shared
|
mkdir /tmp/shared
|
||||||
|
|
||||||
# start the dc
|
# start the dc
|
||||||
docker run -dit --name dc -v /tmp/shared:/shared --hostname krb.domain.test --cap-add SYS_ADMIN icewind1991/samba-krb-test-dc
|
docker run -dit --name dc${FORGEJO_RUN_NUMBER} -v /tmp/shared:/shared --hostname krb.domain.test --cap-add SYS_ADMIN icewind1991/samba-krb-test-dc
|
||||||
DC_IP=$(docker inspect dc --format '{{.NetworkSettings.IPAddress}}')
|
DC_IP=$(docker inspect dc${FORGEJO_RUN_NUMBER} --format '{{.NetworkSettings.IPAddress}}')
|
||||||
|
|
||||||
waitContainer dc
|
waitContainer dc${FORGEJO_RUN_NUMBER}
|
||||||
|
|
||||||
# start apache
|
# start apache
|
||||||
docker run -d --name apache -v $PWD:/var/www/html -v /tmp/shared:/shared --dns $DC_IP --hostname httpd.domain.test icewind1991/samba-krb-test-apache
|
docker run -d --name apache${FORGEJO_RUN_NUMBER} -v $PWD:/var/www/html -v /tmp/shared:/shared --dns $DC_IP --hostname httpd.domain.test icewind1991/samba-krb-test-apache
|
||||||
APACHE_IP=$(docker inspect apache --format '{{.NetworkSettings.IPAddress}}')
|
APACHE_IP=$(docker inspect apache${FORGEJO_RUN_NUMBER} --format '{{.NetworkSettings.IPAddress}}')
|
||||||
|
|
||||||
# add the dns record for apache
|
# add the dns record for apache
|
||||||
docker exec dc samba-tool dns add krb.domain.test domain.test httpd A $APACHE_IP -U administrator --password=passwOrd1
|
docker exec dc${FORGEJO_RUN_NUMBER} samba-tool dns add krb.domain.test domain.test httpd A $APACHE_IP -U administrator --password=passwOrd1
|
||||||
Loading…
Add table
Add a link
Reference in a new issue