saltcorn-samba 0.4.13 → 0.4.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,50 @@ All notable changes to `saltcorn-samba` are documented here.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/).
6
6
 
7
+ ## [0.4.14] – 2026-07-06
8
+
9
+ ### Changed – Code-Review / Aufräumen (keine Verhaltensänderung)
10
+
11
+ Interne QS-Runde nach dem v0.4.13-Fix. Der Bug war behoben, aber die
12
+ Kommentare, Fehlertexte und die Fallback-Logik im Connection-Test
13
+ verwiesen noch auf die alte, mittlerweile widerlegte Hypothese
14
+ (`FileInformationClass=37 hart kodiert`). Alle diese Stellen wurden
15
+ auf den tatsächlichen Root Cause aktualisiert bzw. gelöscht.
16
+
17
+ **readdir-compat.js:**
18
+ - Docstring priorisiert den tatsächlichen Hauptbug (leeres Pattern
19
+ auf Folge-Pages) und schiebt den FileNameOffset-Bug in die Sekundär-
20
+ rolle (defensiv abgefangen, wird bei aktueller Loop nie getriggert).
21
+ - Encoder-Docstring erklärt, dass der `pat.length === 0`-Zweig nur
22
+ noch defensive Sicherheit ist.
23
+
24
+ **smb-client.js:**
25
+ - Der lange, spekulative Kommentar-Block über „Some Samba builds
26
+ reject QUERY_DIRECTORY on the share root because FileInformation-
27
+ Class=37 is hardcoded“ wurde entfernt. Der wahre Grund steht jetzt
28
+ kurz und präzise dort.
29
+ - Die 0xC0000033-Fehlermeldung verweist nicht mehr auf v0.4.12 als Fix
30
+ und nicht mehr auf `tools/diag-basepath.js`, sondern auf
31
+ `tools/diag-wire.js` (das aussagekräftigere Tool).
32
+
33
+ **index.js (Connection-Test-Route):**
34
+ - Der „gelber Hinweis“-Fallback bleibt als Safety Net, wird aber nur
35
+ noch aktiv, wenn `readdir` fehlschlägt und `stat` erfolgreich ist —
36
+ ein Zustand, der seit v0.4.13 nicht mehr auftreten sollte.
37
+ - Der Hinweistext sagt jetzt „unerwarteter Zustand, bitte diag-wire.js
38
+ ausführen“ statt der alten, jetzt falschen Erklärung mit
39
+ `FileInformationClass=37`.
40
+
41
+ **tools/diag-basepath.js:**
42
+ - FIX: `client.disconnect()` → `client.close()`. smb3-client's Client
43
+ hat `close()`, nicht `disconnect()` (das war die marsaud-API). Der
44
+ Aufruf schlug bisher am Ende jedes Diagnostic-Runs mit einer
45
+ TypeError-Meldung fehl, ohne aber das Resultat zu beeinträchtigen.
46
+
47
+ **tools/diag-wire.js:**
48
+ - FIX: Zusätzlich zu `open.close()` wird jetzt auch `client.close()`
49
+ aufgerufen, damit der TCP-Socket sauber geschlossen wird.
50
+
7
51
  ## [0.4.13] – 2026-07-06
8
52
 
9
53
  ### Fixed – **QUERY_DIRECTORY leere Patterns → 0xC0000033 (die eigentliche Ursache)**
package/index.js CHANGED
@@ -1019,21 +1019,18 @@ code{background:#f4f4f4;padding:2px 6px;border-radius:3px;word-break:break-all}<
1019
1019
  })),
1020
1020
  truncated: Array.isArray(listing) && listing.length > 20,
1021
1021
  note: rootNotEnum
1022
- ? "Verbindung + Anmeldung erfolgreich. Der Server erlaubt jedoch " +
1023
- "kein direktes Auflisten des Share-Roots (bekanntes Samba-" +
1024
- "Verhalten mit smb3-client). Bitte setzen Sie einen Basispfad " +
1025
- "in der Plugin-Config (z.\u202fB. einen Unterordner der " +
1026
- "Freigabe) dann funktioniert der File-Manager vollständig."
1022
+ ? "Verbindung + Anmeldung erfolgreich, aber der Share-Root konnte " +
1023
+ "nicht aufgelistet werden (stat OK, readdir schlug fehl). Das ist " +
1024
+ "ein unerwarteter Zustand \u2014 seit v0.4.13 sollte readdir gegen " +
1025
+ "Samba fehlerfrei laufen. Bitte tools/diag-wire.js ausf\u00fchren " +
1026
+ "und den Report melden."
1027
1027
  : baseNotEnum
1028
1028
  ? "Verbindung + Anmeldung erfolgreich, Basispfad \u201e" +
1029
1029
  (listing._basePathForDisplay || testCfg.base_path || "") +
1030
- "\u201c wurde vom Server best\u00e4tigt (stat OK). Das direkte " +
1031
- "Auflisten dieses Ordners lehnt Samba 4.23 mit smb3-client " +
1032
- "aktuell ab (bekannter Bug: FileInformationClass=37 hart " +
1033
- "kodiert, siehe README). Ordner-Unterb\u00e4ume, Datei-Downloads " +
1034
- "und PDF-Ansicht funktionieren \u2014 nur die Wurzel des " +
1035
- "Basispfads kann nicht direkt aufgelistet werden. Workaround: " +
1036
- "tieferen Basispfad setzen oder Unterordner ansprechen."
1030
+ "\u201c wurde vom Server best\u00e4tigt (stat OK), das direkte " +
1031
+ "Auflisten schlug aber fehl. Das ist ein unerwarteter Zustand \u2014 " +
1032
+ "seit v0.4.13 sollte readdir gegen Samba fehlerfrei laufen. Bitte " +
1033
+ "tools/diag-wire.js ausf\u00fchren und den Report melden."
1037
1034
  : undefined,
1038
1035
  });
1039
1036
  } catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "saltcorn-samba",
3
- "version": "0.4.13",
3
+ "version": "0.4.14",
4
4
  "description": "Saltcorn plugin: browse, upload, rename and delete files on a Samba/CIFS share via SMB 3.1.1 (AES-CMAC signing, optional encryption). File-manager view, directory tree, inline PDF viewer, external-app open (smb://).",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/readdir-compat.js CHANGED
@@ -1,24 +1,30 @@
1
1
  "use strict";
2
2
 
3
3
  /**
4
- * readdir-compat.js — saltcorn-samba 0.4.13
4
+ * readdir-compat.js — saltcorn-samba 0.4.14
5
5
  *
6
6
  * Behebt zwei QUERY_DIRECTORY-Wire-Bugs in smb3-client@0.2.0 die
7
7
  * gegen Samba 4.23 zu STATUS_OBJECT_NAME_INVALID (0xC0000033) führen.
8
8
  *
9
- * BUG 1 (FileNameOffset bei leerem Pattern):
9
+ * BUG 1 (leeres Pattern auf Folge-Pages) ─ Hauptursache des 0xC0000033:
10
+ * smb3-client's `readdirAll` sendet ab der 2. Enumeration-Page
11
+ * `searchPattern=""`. Windows toleriert das, Samba 4.23 lehnt es
12
+ * strikt ab: `source3/smbd/smb2_query_directory.c` prüft
13
+ * `in_file_name[0] == '\0'` und antwortet mit
14
+ * STATUS_OBJECT_NAME_INVALID.
15
+ * Fix (in readdirAllFixed): Auf jeder Page `*` senden. RESTART_SCANS
16
+ * nur beim ersten Request. Samba beendet nach der letzten Seite
17
+ * sauber mit STATUS_NO_MORE_FILES.
18
+ *
19
+ * BUG 2 (FileNameOffset bei leerem Pattern) ─ defensiv abgefangen:
10
20
  * smb3-client's `encodeQueryDirectoryRequest` setzt `FileNameOffset`
11
21
  * immer auf 96 — auch wenn `FileNameLength === 0` gesendet wird.
12
22
  * MS-SMB2 §2.2.33 verlangt für diesen Fall FileNameOffset = 0.
13
- *
14
- * BUG 2 (Leeres Pattern auf Folge-Pages): ← Der Hauptbug!
15
- * smb3-client sendet ab der 2. Enumeration-Page `searchPattern=""`.
16
- * Windows toleriert das, Samba 4.23 lehnt es strikt ab. Belegt via
17
- * diag-wire.js: `smb2_query_directory.c` prüft `in_file_name[0] ==
18
- * '\0'` und antwortet dann mit STATUS_OBJECT_NAME_INVALID.
19
- * Fix: Auf jeder Page `*` senden. RESTART_SCANS nur beim ersten Mal.
20
- * Samba beendet die Enumeration dann korrekt mit
21
- * STATUS_NO_MORE_FILES auf einem Folge-Request ohne RESTART_SCANS.
23
+ * Da wir seit Bug-1-Fix ohnehin nie mit leerem Pattern senden, kann
24
+ * dieser Bug nicht mehr getriggert werden — encodeQueryDirectory-
25
+ * RequestFixed behandelt den Fall trotzdem spec-konform, falls ein
26
+ * Aufrufer den Encoder direkt benutzt oder ein zukünftiger Server
27
+ * noch strenger prüft.
22
28
  *
23
29
  * Strategie:
24
30
  * Statt smb3-client's `client.readdir()` / `readdirAll` verwenden wir
@@ -26,8 +32,9 @@
26
32
  * verwendet (Open, Close, Tree-Connect bleiben unverändert) und nur
27
33
  * die kaputte QUERY_DIRECTORY-Loop durch eine spec-konforme ersetzt.
28
34
  *
29
- * Nur die interne wire-Struktur wird via file:// URL importiert, weil
30
- * smb3-client's `exports`-Gate keine Subpath-Imports zulässt.
35
+ * Die internen wire-Module werden via `file://` URL geladen, weil
36
+ * smb3-client's `exports`-Gate keine Subpath-Imports über den
37
+ * Package-Namen zulässt (nicht einmal `smb3-client/package.json`).
31
38
  */
32
39
 
33
40
  const fs = require("fs");
@@ -134,9 +141,15 @@ function loadInternals() {
134
141
 
135
142
  /**
136
143
  * Spec-konformer Encoder für SMB2 QUERY_DIRECTORY (MS-SMB2 §2.2.33).
137
- * Anders als das Original:
138
- * - FileNameOffset = 0, wenn kein Suchpattern (statt 96)
139
- * Ansonsten identisch (Struktur + Padding-Byte).
144
+ *
145
+ * Unterschied zum Original in smb3-client@0.2.0:
146
+ * `FileNameOffset` wird auf 0 gesetzt, wenn `pat.length === 0`
147
+ * (statt hart auf 64+32=96). MS-SMB2 §2.2.33 verlangt bei
148
+ * `FileNameLength=0` genau `FileNameOffset=0`.
149
+ *
150
+ * In der aktuellen Compat-Loop wird immer `pat="*"` gesendet, daher
151
+ * wird dieser Zweig nie erreicht. Er bleibt als defensive Absicherung
152
+ * gegen Aufrufer, die den Encoder direkt mit leerem Pattern nutzen.
140
153
  */
141
154
  function encodeQueryDirectoryRequestFixed(I, req) {
142
155
  const pat = req.searchPattern
package/smb-client.js CHANGED
@@ -227,8 +227,8 @@ async function buildClient(config) {
227
227
  * Convert a readdirCompat rich-Dirent (which already carries name,
228
228
  * size, mtime, ctime, and isDirectory()) directly to the legacy
229
229
  * `@marsaud/smb2`-compatible shape the rest of the plugin expects.
230
- * No extra stat roundtrip needed — v0.4.12 gets attributes straight
231
- * from the QUERY_DIRECTORY response.
230
+ * No extra stat roundtrip needed — attributes come straight from the
231
+ * single QUERY_DIRECTORY response.
232
232
  */
233
233
  function mapDirent(dirent) {
234
234
  return {
@@ -255,42 +255,33 @@ async function buildClient(config) {
255
255
  */
256
256
  async readdir(rel) {
257
257
  const full = resolvePath(rel);
258
- // v0.4.12: readdirCompat ist der ALLEINIGE readdir-Pfad. Grund:
259
- // smb3-client@0.2.0 hat einen Wire-Format-Bug in
260
- // encodeQueryDirectoryRequest, der gegen Samba 4.23 zu
261
- // STATUS_OBJECT_NAME_INVALID (0xC0000033) führt. readdirCompat
262
- // implementiert QUERY_DIRECTORY MS-SMB2-§2.2.33-konform und
263
- // umgeht damit den Bug. Es gibt keinen Fallback auf
264
- // client.readdir(), weil das den bekannten Bug hervorruft.
258
+ // readdirCompat ist der ALLEINIGE readdir-Pfad. Grund: smb3-
259
+ // client@0.2.0 hat zwei QUERY_DIRECTORY-Wire-Bugs, die gegen
260
+ // Samba 4.23 zu STATUS_OBJECT_NAME_INVALID (0xC0000033) führen
261
+ // (leeres Pattern auf Folge-Pages + falscher FileNameOffset).
262
+ // readdirCompat implementiert QUERY_DIRECTORY MS-SMB2-§2.2.33-
263
+ // konform und umgeht beide Bugs. Kein Fallback auf
264
+ // client.readdir() das würde die Bugs reproduzieren.
265
265
  let dirents;
266
266
  try {
267
267
  dirents = await readdirCompat(client, full, { rich: true });
268
268
  } catch (errCompat) {
269
269
  const err = errCompat;
270
- // Some Samba builds (observed on 4.20+/4.23+) reject
271
- // SMB2 QUERY_DIRECTORY on the *share root* with
272
- // STATUS_OBJECT_NAME_INVALID (0xC0000033) because smb3-client
273
- // asks for FileIdBothDirectoryInformation (class 37) on a
274
- // handle opened with an empty filename. We cannot swap the
275
- // information class from userland, and Samba refuses both
276
- // "." (→ STATUS_OBJECT_NAME_NOT_FOUND) and "*" (→ CREATE with
277
- // wildcard is protocol-illegal). The clean way out is:
278
- // require the caller to configure a real base_path so every
279
- // readdir happens inside a directory the server can enumerate.
280
270
  const msg = String((err && err.message) || err || "");
281
271
  // Falls der Compat-Pfad selbst mit 0xC0000033 zurückkommt,
282
272
  // liegt entweder ein weiterer, unbekannter Wire-Bug vor oder
283
- // Samba lehnt aus einem anderen Grund ab. Wir geben eine
284
- // gezielte Meldung mit Hinweis auf den Bug-Report.
273
+ // Samba lehnt aus einem anderen Grund ab (z. B. fehlende
274
+ // Rechte auf die Zielressource). Wir geben eine gezielte
275
+ // Meldung mit Handlungsanweisung.
285
276
  if (/0xC0000033|OBJECT_NAME_INVALID/i.test(msg)) {
286
277
  const e = new Error(
287
- "Samba lehnt QUERY_DIRECTORY auf diesem Pfad ab " +
288
- "(STATUS_OBJECT_NAME_INVALID, 0xC0000033). " +
289
- "Der bekannte smb3-client-Wire-Bug wurde in v0.4.12 gefixt " +
290
- "falls dieser Fehler weiterhin auftritt, liegt ein zweiter, " +
291
- "noch unbekannter Wire-Format-Fehler vor. Bitte " +
292
- "tools/diag-basepath.js ausführen und Report zurückschicken. " +
293
- "Details: " +
278
+ "Samba lehnt QUERY_DIRECTORY auf diesem Pfad unerwartet ab " +
279
+ "(STATUS_OBJECT_NAME_INVALID, 0xC0000033). Die bekannten " +
280
+ "smb3-client-Wire-Bugs sind in dieser Plugin-Version " +
281
+ "bereits gepatcht — falls dieser Fehler dennoch auftritt, " +
282
+ "liegt ein bislang unbekannter Wire-Format-Fehler oder ein " +
283
+ "Rechteproblem vor. Bitte tools/diag-wire.js ausführen " +
284
+ "und den Report zurücksenden. Details: " +
294
285
  msg
295
286
  );
296
287
  e.cause = err;
@@ -320,9 +311,9 @@ async function buildClient(config) {
320
311
  }
321
312
  throw err;
322
313
  }
323
- // v0.4.12: readdirCompat gibt schon Rich-Dirents zurück (Name,
324
- // Größe, mtime, ctime, isDirectory). Kein zusätzlicher stat-Fan-out
325
- // nötig — ein einziger QUERY_DIRECTORY-Roundtrip liefert alles.
314
+ // readdirCompat gibt Rich-Dirents zurück (Name, Größe, mtime,
315
+ // ctime, isDirectory). Kein zusätzlicher stat-Fan-out nötig —
316
+ // ein einziger QUERY_DIRECTORY-Roundtrip liefert alles.
326
317
  return dirents.map(mapDirent);
327
318
  },
328
319
 
@@ -91,7 +91,10 @@ async function main() {
91
91
  step++;
92
92
  }
93
93
 
94
- await client.disconnect();
94
+ // smb3-client's Client has close(), not disconnect() — the old
95
+ // marsaud API used disconnect. Use close() and ignore errors so a
96
+ // failing probe still tears down cleanly.
97
+ try { await client.close(); } catch (_) {}
95
98
  console.log("Done.");
96
99
  }
97
100
 
@@ -325,6 +325,9 @@ async function main() {
325
325
  try {
326
326
  await open.close();
327
327
  } catch (_) {}
328
+ try {
329
+ await client.close();
330
+ } catch (_) {}
328
331
  console.log("\nDone.");
329
332
  }
330
333