Giter VIP home page Giter VIP logo

node-smb-server's Introduction

SMB Server for Node.js

⚠️ This repository is no longer actively maintained.

Overwiew

node-smb-server is an open-source JavaScript implementation of the SMB/CIFS file sharing protocol.

Some highlights:

  • pure JavaScript
  • fully configurable/customizable
  • extensible: allows to expose non-filesystem based data as a mountable file system via an abstract backend SPI (similar to Samba's VFS)

Note:

The current implementation works with Finder on OS X (Yosemite, El Capitan, Sierra). More recent OS X versions might work as well but they haven't been tested.

Windows is not supported. File Explorer only supports the standard SMB port 445. It's virtually impossible to run a custom SMB server listening on port 445 on Windows. See here and here for related discussions.

Installation

npm install node-smb-server

or

git clone https://github.com/adobe/node-smb-server.git
cd node-smb-server
npm install

Getting started

Execute the following commands in a terminal:

cd <node-smb-server install dir>
npm start

In Finder, open the 'Connect to Server' dialog (⌘K) and enter the url smb://localhost:8445/fs (user: test, password: test).

Getting your hands dirty

User management

The following users are pre-configured: test/test, admin/admin, guest/<empty password>

Users can be edited in the config.json file:

...
"users" : {
    "test" : {
      "lmHash" : "01fc5a6be7bc6929aad3b435b51404ee",
      "ntlmHash" : "0cb6948805f797bf2a82807973b89537"
    },
    "admin" : {
      "lmHash" : "f0d412bd764ffe81aad3b435b51404ee",
      "ntlmHash" : "209c6174da490caeb422f3fa5a7ae634"
    },
    "guest" : {
      "lmHash" : "aad3b435b51404eeaad3b435b51404ee",
      "ntlmHash" : "31d6cfe0d16ae931b73c59d7e0c089c0"
    }
  }
...

Password hashes can be computed by running:

node createhash.js

Share configuration

Share configurations can be edited in the config.json file, e.g.:

...
 "shares": {
    "FS": {
      "backend": "fs",
      "description": "fs-based test share",
      "path": "./smbroot"
    },
    "JCR": {
      "backend": "jcr",
      "description": "AEM-based test share",
      "host": "localhost",
      "port": 4502,
      "protocol": "http:",
      "auth": {
        "user": "<user>",
        "pass": "<pwd>"
      },
      "path": "/",
      "maxSockets": 64,
      "contentCacheTTL": 30000,
      "binCacheTTL": 600000
    },
...

Developing a custom backend

Consider the following example use case:

You would like to enable your desktop applications to access data and documents stored in a RDBMS or a Cloud-based service.

You could write a custom backend by implementing the Share, Tree and File interfaces of the virtual backend SPI (lib/spi). Check out the existing implementations (lib/backends) to get an idea.

Current Status

  • Implements CIFS and MS-SMB 1.0.
  • Support for SMB2 is currently work in progress.
  • Supports LM, LMv2, NTLM, NTLMSSP authentication protocols
  • Supported backends:
    • local file system (lib/backends/fs)
    • JCR (lib/backends/jcr)
    • AEM Assets (lib/backends/dam)
  • Tested with Finder on OS X (Yosemite, El Capitan, Sierra).

ToDo's

  • Test with other clients on other platforms (Windows, Linux).
  • Test cases/suite

CIFS/SMB

  • missing NT_TRANSACT subcommands
  • missing TRANSACTION subcommands
  • missing TRANSACTION2 subcommand information levels
  • missing CIFS commands:
    • TRANSACTION_SECONDARY
    • TRANSACTION2_SECONDARY
    • NT_TRANSACT_SECONDARY
    • OPEN_PRINT_FILE
  • support for named streams?
  • SMB Signing?
  • proper implementation of LOCKING_ANDX?

SMB Versions 2 and 3

Check/Implement the following protocol extensions/versions:

Specifications

Contributing

If you are interested in contributing to this project, check out our contribution guidelines!

node-smb-server's People

Contributors

dominique-pfister avatar filmaj avatar mfrisbey avatar paladugu82 avatar sidhyatikku avatar stefan-guggisberg avatar tripodsan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

node-smb-server's Issues

Action required: Greenkeeper could not be activated 🚨

🚨 You need to enable Continuous Integration on Greenkeeper branches of this repository. 🚨

To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because it uses your CI build statuses to figure out when to notify you about breaking changes.

Since we didn’t receive a CI status on the greenkeeper/initial branch, it’s possible that you don’t have CI set up yet. We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.

If you have already set up a CI for this repository, you might need to check how it’s configured. Make sure it is set to run on all new branches. If you don’t want it to run on absolutely every branch, you can whitelist branches starting with greenkeeper/.

Once you have installed and configured CI on this repository correctly, you’ll need to re-trigger Greenkeeper’s initial pull request. To do this, please click the 'fix repo' button on account.greenkeeper.io.

Notification When New Request Queued

In order to display current status to users, it's become necessary to send notifications when new records are added to the request queue, or when existing records are modified. The proposed solution is to modify the request queue to send a queuechanged event whenever these additions or modifications happen. The event won't supply any additional arguments because it's primary purpose is to simply notify that there have been changes.

Reverting versions does not re-sync file

If an asset is reverted to a previous version in dam, the locally cached file is not updated. To reproduce:

  1. Start SMB server and connect to the RQ backend
  2. Open a Finder window and add a new asset to a folder
  3. Replace the asset with a different version or make changes to the asset and save
  4. Use DAM user interface to revert to the previous version of the asset
  5. Return to Finder window and open the file. Note that it is still the previous version

Disappearing Files

There are cases where files will disappear from a directory in Finder (seemingly randomly). The disappearances are caused by duplicate file names. To reproduce:

  • Use the RQ backend
  • In DAM, create two assets: testfile.jpg and TESTFILE.JPG
  • Start the server and navigate to the directory containing the files
  • Note that initially there are two files with the exact same name, but after a few seconds one of them will disappear

Crash in RQ backend when listing large directories

The server crashes in certain conditions when using the RQ backend and listing the contents of very large directories. The issue does not manifest when the server is run standalone, but when running through node.js as a shared library there is a crash. To reproduce:

  • Create a directory in DAM with 1,500 files
  • Mount the server and browse to the directory
  • Observe the crash

Question: Is this comparable to fuse?

I have a project where I'd like to mount a virtual filesystem based on a directory structure from a website. On Windows, I have used dokan to accomplish this. On Mac, I was looking at osxfuse. Would this project be similar solution to osxfuse? I have zero experience with smb. From looking around this seems to be familiar. I have also looked at Kernelless Filesystem (KFS), but I read somewhere that it doesn't support simultaneous IO and can be slow. Any information would be greatly appreciated.

Crash when files missing in local cache

The SMB server is crashing in the case where the rq backend attempts to sync a file that no longer exists in the local cache. To reproduce:

  • Launch an SMB server using the rq backend and connect
  • Edit an existing file and then immediately shut down the server when the save is complete (before the server has a chance to sync the file)
  • Remove the modified file from the local cache
  • Relaunch the server and observe the crash

android smb client occurs errors

Hello

node-smb-server works with windows smb client. I tried.
but I tried a few apps on android, it occurs errors below

 node ./index.js

info: [SRV] logging initialized.
info: [SRV] configuration successfully read: /data/data/com.termux/files/home/node-smb-server/config.json
(node:9826) Warning: Accessing non-existent property 'padLevels' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)
info: [SRV] [9826] SMB server started listening on port 445
info: [SRV] established client connection #1 from [192.168.0.100:58224] -> [192.168.0.103:445]
error: [SMB] encountered unhandled exception at the handler level. exiting message=The value of "offset" is out of range. It must be >= 0 and <= 72. Received 76, stack=RangeError [ERR_OUT_OF_RANGE]: The value of "offset" is out of range. It must be >= 0 and <= 72. Received 76
    at boundsError (internal/buffer.js:77:9)
    at Buffer.readUInt32LE (internal/buffer.js:211:5)
    at netShareEnumAll (/data/data/com.termux/files/home/node-smb-server/lib/dcerpc/pdu/request.js:200:29)
    at handle (/data/data/com.termux/files/home/node-smb-server/lib/dcerpc/pdu/request.js:70:7)
    at handle (/data/data/com.termux/files/home/node-smb-server/lib/smb/cmd/trans/trans_transact_nmpipe.js:137:5)
    at handle (/data/data/com.termux/files/home/node-smb-server/lib/smb/cmd/transaction.js:129:5)
    at Domain.<anonymous> (/data/data/com.termux/files/home/node-smb-server/lib/smb/handler.js:94:11)
    at Domain.run (domain.js:373:14)
    at /data/data/com.termux/files/home/node-smb-server/lib/smb/handler.js:92:11
    at /data/data/com.termux/files/home/node-smb-server/node_modules/async/lib/async.js:181:20, code=ERR_OUT_OF_RANGE, removeListener=function updateExceptionCapture() {
  if (stack.every((domain) => domain.listenerCount('error') === 0)) {
    setUncaughtExceptionCaptureCallback(null);
  } else {
    setUncaughtExceptionCaptureCallback(null);
    setUncaughtExceptionCaptureCallback((er) => {
      return process.domain._errorHandler(er);
    });
  }
}, newListener=function updateExceptionCapture() {
  if (stack.every((domain) => domain.listenerCount('error') === 0)) {
    setUncaughtExceptionCaptureCallback(null);
  } else {
    setUncaughtExceptionCaptureCallback(null);
    setUncaughtExceptionCaptureCallback((er) => {
      return process.domain._errorHandler(er);
    });
  }
}, error=function (err) {
          logger.error('encountered unhandled exception at the handler level. exiting', err);
          process.exit(1);
        }, _eventsCount=3, _maxListeners=undefined, members=[], domainThrown=true
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] start: `node ./index.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

Folder encoding error

There are issues in the server when attempting to create a folder containing multibyte characters. To reproduce:

  • In a local directory, create a new folder called 이두吏讀
  • Start the server and mount the dam or rq backend
  • Copy the newly created folder and paste it into the mounted directory
  • Check the directory that was created in DAM. Note that the characters in the name are incorrect

This is due to the way that the dam backend is using the assets api to create directories. The proposed fix is to change the request so that it uses a JSON payload with a content type whose charset is utf-8.

Crash on network disconnect

The server crashes due to an unhandled exception when there is a network disconnect. To reproduce:

  • Start the server and mount the rq backend (make sure to use a target DAM instance that requires travel of the network. i.e. not localhost.
  • Open finder and browse to any folder
  • Disconnect from the network by unplugging the network cable or turning off wifi
  • Try to navigate to a different folder using Finder
  • Note the crash

Action required: Greenkeeper could not be activated 🚨

🚨 You need to enable Continuous Integration on Greenkeeper branches of this repository. 🚨

To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because it uses your CI build statuses to figure out when to notify you about breaking changes.

Since we didn’t receive a CI status on the greenkeeper/initial branch, it’s possible that you don’t have CI set up yet. We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.

If you have already set up a CI for this repository, you might need to check how it’s configured. Make sure it is set to run on all new branches. If you don’t want it to run on absolutely every branch, you can whitelist branches starting with greenkeeper/.

Once you have installed and configured CI on this repository correctly, you’ll need to re-trigger Greenkeeper’s initial pull request. To do this, please click the 'fix repo' button on account.greenkeeper.io.

Temporary folders being synced

There are cases where folders with temporary file names are being synced to the remote repository. To reproduce:

  • Launch the server using the rq backend on osx
  • Edit an existing image by opening it in Preview, rotating it, then clicking save
  • Log into the remote repository and note that there is now a folder named .TemporaryItems in the same directory as the image
  • Attempting to delete a directory with a temp file name results in the unexpected behavior of deleting the parent directory

Reusable logs

While good in concept, the idea of sending log messages to different files proves challenging in practice. It makes following the process flow difficult and does not provide a clear big picture of what's happening.

I propose extending the logging initialization so that it's possible to configure a logger to reuse another logger's transport. Current log configurations will remain unchanged, but, as an example, it will be possible through configuration to have multiple loggers write to the same file.

error upon connection: encountered unhandled exception at the handler level. exiting message=The value of "offset" is out of range

hi, the server crashed upon smb connection

npm start

[email protected] start /root/node_modules/node-smb-server
node ./index.js

info: [SRV] logging initialized.
info: [SRV] configuration successfully read: /root/node_modules/node-smb-server/config.json
info: [SRV] [9407] SMB server started listening on port 445
info: [SRV] established client connection #1 from [10.162.130.12:58130] -> [10.162.140.139:445]
error: [SMB] encountered unhandled exception at the handler level. exiting message=The value of "offset" is out of range. It must be >= 0 and <= 72. Received 73, stack=RangeError [ERR_OUT_OF_RANGE]: The value of "offset" is out of range. It must be >= 0 and <= 72. Received 73
at boundsError (internal/buffer.js:77:9)
at Buffer.readUInt16LE (internal/buffer.js:234:5)
at Object.extractUnicodeBytes (/root/node_modules/node-smb-server/lib/utils.js:190:14)
at handle (/root/node_modules/node-smb-server/lib/smb/cmd/session_setup_andx.js:83:19)
at Domain. (/root/node_modules/node-smb-server/lib/smb/handler.js:94:11)
at Domain.run (domain.js:370:14)
at /root/node_modules/node-smb-server/lib/smb/handler.js:92:11
at /root/node_modules/node-smb-server/node_modules/async/lib/async.js:181:20
at iterate (/root/node_modules/node-smb-server/node_modules/async/lib/async.js:262:13)
at Object.async.forEachOfSeries.async.eachOfSeries (/root/node_modules/node-smb-server/node_modules/async/lib/async.js:281:9), code=ERR_OUT_OF_RANGE, removeListener=function updateExceptionCapture() {
if (stack.every((domain) => domain.listenerCount('error') === 0)) {
setUncaughtExceptionCaptureCallback(null);
} else {
setUncaughtExceptionCaptureCallback(null);
setUncaughtExceptionCaptureCallback((er) => {
return process.domain._errorHandler(er);
});
}
}, newListener=function updateExceptionCapture() {
if (stack.every((domain) => domain.listenerCount('error') === 0)) {
setUncaughtExceptionCaptureCallback(null);
} else {
setUncaughtExceptionCaptureCallback(null);
setUncaughtExceptionCaptureCallback((er) => {
return process.domain._errorHandler(er);
});
}
}, error=function (err) {
logger.error('encountered unhandled exception at the handler level. exiting', err);
process.exit(1);
}, _eventsCount=3, _maxListeners=undefined, members=[], domainThrown=true
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] start: node ./index.js
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR! /root/.npm/_logs/2020-07-30T08_02_24_508Z-debug.log

Odd read-only behaviors

Many consuming applications don't handle read only files well. Some display an appropriate error message, others appear to save successfully, and some others may even crash.

To alleviate these issues, it's recommended that the RQ backend no longer enforce read only files at write or read time. Instead, files will always be writeable locally. The read-only status will be enforced when the file is synced to the server in the background; if a file is checked out by another user then a message will show up in the background status window indicating that the latest changes can't be synced because the file is checked out.

Support for linux

Hello. I've tried to use the package on linux, but it doesn't work.

image

Output (multiple attempts)

$ npm start

> [email protected] start /home/maxjf1/node-smb-server
> node ./index.js

info: [SRV] logging initialized.
info: [SRV] configuration successfully read: /home/maxjf1/node-smb-server/config.json
(node:31341) Warning: Accessing non-existent property 'padLevels' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)
info: [SRV] [31341] SMB server started listening on port 8445
info: [SRV] established client connection #1 from [127.0.0.1:47514] -> [127.0.0.1:8445]
info: [SRV] client #1 disconnected (received: 0kb, sent: 0kb)
info: [SRV] established client connection #2 from [127.0.0.1:47516] -> [127.0.0.1:8445]
error: [SMB] encountered unsupported command 0x1 'SESSION_SETUP'
info: [SRV] client #2 disconnected (received: 0kb, sent: 0kb)
info: [SRV] established client connection #3 from [127.0.0.1:47522] -> [127.0.0.1:8445]
error: [SMB] encountered unsupported command 0x1 'SESSION_SETUP'
info: [SRV] client #3 disconnected (received: 0kb, sent: 0kb)
info: [SRV] established client connection #4 from [127.0.0.1:47526] -> [127.0.0.1:8445]
error: [SMB] encountered unsupported command 0x1 'SESSION_SETUP'
info: [SRV] client #4 disconnected (received: 0kb, sent: 0kb)
info: [SRV] established client connection #5 from [127.0.0.1:47532] -> [127.0.0.1:8445]
error: [SMB] encountered unsupported command 0x1 'SESSION_SETUP'
info: [SRV] client #5 disconnected (received: 0kb, sent: 0kb)
info: [SRV] established client connection #6 from [127.0.0.1:47534] -> [127.0.0.1:8445]
error: [SMB] encountered unsupported command 0x1 'SESSION_SETUP'
info: [SRV] client #6 disconnected (received: 0kb, sent: 0kb)
info: [SRV] established client connection #7 from [127.0.0.1:47536] -> [127.0.0.1:8445]
error: [SMB] encountered unsupported command 0x1 'SESSION_SETUP'
info: [SRV] client #7 disconnected (received: 0kb, sent: 0kb)
info: [SRV] established client connection #8 from [127.0.0.1:47538] -> [127.0.0.1:8445]
error: [SMB] encountered unsupported command 0x1 'SESSION_SETUP'
info: [SRV] client #8 disconnected (received: 0kb, sent: 0kb)
info: [SRV] established client connection #9 from [127.0.0.1:47540] -> [127.0.0.1:8445]
error: [SMB] encountered unsupported command 0x1 'SESSION_SETUP'
info: [SRV] client #9 disconnected (received: 0kb, sent: 0kb)
info: [SRV] established client connection #10 from [127.0.0.1:47546] -> [127.0.0.1:8445]
error: [SMB] encountered unsupported command 0x1 'SESSION_SETUP'
info: [SRV] client #10 disconnected (received: 0kb, sent: 0kb)
info: [SRV] established client connection #11 from [127.0.0.1:47610] -> [127.0.0.1:8445]
error: [SMB] encountered unsupported command 0x1 'SESSION_SETUP'
info: [SRV] client #11 disconnected (received: 0kb, sent: 0kb)

Unhandled exceptions while writing content

There are cases where fetching content from jcr will generate an unhandled exception. One example is if there isn't enough disk space.

The proposed fix is to listen for the output stream's error event and send the exception through the smb server's callback mechanism so it can be handled.

Invalid NTLMSSP message signature, Ubuntu 16.04 LTS x64

server.log
smb.log

info: [SRV] logging initialized.
info: [SRV] configuration successfully read: /home/marc/Downloads/node-smb-server-master/config.json
info: [SRV] [15117] SMB server started listening on port 8445
info: [SRV] established client connection #1 from [127.0.0.1:53272] -> [127.0.0.1:8445]
warn: [SRV] invalid NTLMSSP message signature: data: 0x604806062b060105
info: [SRV] client #1 disconnected (received: 0kb, sent: 0kb)
info: [SRV] established client connection #2 from [127.0.0.1:53274] -> [127.0.0.1:8445]
warn: [SRV] invalid NTLMSSP message signature: data: 0x604806062b060105
info: [SRV] client #2 disconnected (received: 0kb, sent: 0kb)
info: [SRV] established client connection #3 from [127.0.0.1:53276] -> [127.0.0.1:8445]
warn: [SRV] invalid NTLMSSP message signature: data: 0x604806062b060105
warn: [SRV] invalid NTLMSSP message signature: data: 0x604806062b060105
info: [SRV] client #3 disconnected (received: 0kb, sent: 0kb)
info: [SRV] established client connection #4 from [127.0.0.1:53278] -> [127.0.0.1:8445]
warn: [SRV] invalid NTLMSSP message signature: data: 0x604806062b060105
info: [SRV] client #4 disconnected (received: 0kb, sent: 0kb)
info: [SRV] established client connection #5 from [127.0.0.1:53280] -> [127.0.0.1:8445]
warn: [SRV] invalid NTLMSSP message signature: data: 0x604806062b060105
warn: [SRV] invalid NTLMSSP message signature: data: 0x604806062b060105
info: [SRV] client #5 disconnected (received: 0kb, sent: 0kb)
info: [SRV] established client connection #6 from [127.0.0.1:53282] -> [127.0.0.1:8445]
warn: [SRV] invalid NTLMSSP message signature: data: 0x604806062b060105
info: [SRV] client #6 disconnected (received: 0kb, sent: 0kb)

OS: Ubuntu 16.04 LTS x64
Node: v9.11.2

Add method to clear local cache

There are cases where it would be helpful to programmatically clear the rq backend's local cache, being sure to preserve files that are in conflict or queued for update. It is proposed to add a new method to the smbserver for kicking off this process.

smbserver.js error

Error: Cannot find module './defaultauthenticator'
at Function.Module._resolveFilename (module.js:440:15)
at Function.Module._load (module.js:388:25)
at Module.require (module.js:468:17)
at require (internal/module.js:20:19)
at Object. (/root/node-smb-server/lib/smbserver.js:25:28)
at Module._compile (module.js:541:32)
at Object.Module._extensions..js (module.js:550:10)
at Module.load (module.js:458:32)
at tryModuleLoad (module.js:417:12)
at Function.Module._load (module.js:409:3)

Failures with dot names

There are various failures that occur in the SMB server if a folder whose name begins with a period ends up in JCR. In particular, a folder will appear as empty in Finder if such a sub folder exists. There was a previous issue where these kinds of folders were mistakenly synced to JCR, so the server needs to be able to handle the case gracefully. JCR in general does not handle names beginning with a period well.

The proposed solution is to explicitly exclude these types of folders from JCR lists so that the server doesn't attempt to consume them. This will effectively ignore these kinds of folders.

SMB server seems not to work on Raspberry Pi 3 (armv7l)

When running the untouched checkout from this git repo on my Mac everything works as expected (node v6.9.3). But when running the same untouched checkout on the Raspberry Pi 3 I can connect to the server, enter a user name and a password (it seems that they are validated) but then a message comes up that there might be no shares or I haven't enough rights to access them. See the log (everything set to debug) below.

By comparing this log to the log of the working instance on my Mac I discovered the following differences:

(1)
debug: [SMB] [SESSION_SETUP_ANDX] maxBufferSize: 33028, maxMpxCount: 50, vcNumber: 454, sessionKey: 1, capabilities: 10000000000000001100000001011100, accountName: test, primaryDomain: ERIC, nativeOS: Mac OS X 10.10, nativeLanMan: SMBFS 3.0.0
vcNumber is 454 but on the working instance it is 455

(2)
debug: [SPI] [ipc] tree.open /srvsvc
debug: [SPI] [ipc] file.open /srvsvc
These two lines are printed on the working copy but not on the Pi

(3)
debug: [SMB] [TRANS_TRANSACT_NMPIPE] fid: 1 [fileName: srvsvc], data: 050000031000000054000000000000003c00000000000f00010000000500000000000000050000006500720069006300000000000100000001000000010000000000000000000000ffffffff0100000000000000
The data value differs and therefore also the variables totalDataCount and dataCount in the line before

Log from the Pi:

# uname -a
Linux eric 4.4.50-v7+ #970 SMP Mon Feb 20 19:18:29 GMT 2017 armv7l GNU/Linux
# node -v
v6.10.2
# node index.js 
info: [SRV] logging initialized.
info: [SRV] configuration successfully read: 
debug: [SRV] registering share syncfilestart event
debug: [SRV] registering share syncfileend event
debug: [SRV] registering share syncfileerr event
debug: [SRV] registering share syncfileabort event
debug: [SRV] registering share syncfileprogress event
debug: [SRV] registering share syncerr event
debug: [SRV] registering share syncpurged event
debug: [SRV] registering share syncconflict event
debug: [SRV] registering share folderlist event
debug: [SRV] registering share requestqueueinit event
info: [SRV] [3546] SMB server started listening on port 8445
info: [SRV] established client connection #1 from [192.168.0.2:61246] -> [192.168.0.9:8445]
debug: [SMB] [NEGOTIATE] dialects: NT LM 0.12,SMB 2.002,SMB 2.???
debug: [SMB] [SESSION_SETUP_ANDX] maxBufferSize: 33028, maxMpxCount: 50, vcNumber: 454, sessionKey: 1, capabilities: 10000000000000001100000001011100, accountName: test, primaryDomain: ERIC, nativeOS: Mac OS X 10.10, nativeLanMan: SMBFS 3.0.0
debug: [SMB] [TREE_CONNECT_ANDX] flags: 1000, password: 00, service: ?????, path: \\eric\IPC$
debug: [SMB] [NT_CREATE_ANDX] flags: 10000, rootDirectoryFID: 0, desiredAccess: 11000000000000000000000000000000, allocationSize: 0, extFileAttributes: 10000000, shareAccess: 11, createDisposition: 0x1, createOptions: 0, impersonationLevel: 0x2, securityFlags: 0, fileName: \srvsvc
debug: [SMB] [TRANSACTION][TRANS_TRANSACT_NMPIPE] totalParameterCount: 0, parameterCount: 0, totalDataCount: 72, dataCount: 72, flags: 0
debug: [SMB] [TRANS_TRANSACT_NMPIPE] fid: 1 [fileName: srvsvc], data: 05000b0310000000480000000100000000800080000000000100000000000100c84f324b7016d30112785a47bf6ee18803000000045d888aeb1cc9119fe808002b10486002000000
debug: [DCERPC] bound to SRVSVC v3.0 (4b324fc8-1670-01d3-1278-5a47bf6ee188)
debug: [SMB] [TRANSACTION][TRANS_TRANSACT_NMPIPE] totalParameterCount: 0, parameterCount: 0, totalDataCount: 84, dataCount: 84, flags: 0
debug: [SMB] [TRANS_TRANSACT_NMPIPE] fid: 1 [fileName: srvsvc], data: 050000031000000054000000000000003c00000000000f00010000000500000000000000050000006500720069006300000000000100000001000000010000000000000000000000ffffffff0100000000000000
debug: [DCERPC] NetShareEnumAll (SRVSVC v3.0)
debug: [SMB] [CLOSE] fid: 1 [fileName: srvsvc], lastModified: 4294967295
debug: [SMB] [TREE_DISCONNECT] tid: 1
debug: [SMB] [LOGOFF_ANDX] uid: 1
info: [SRV] client #1 disconnected (received: 1kb, sent: 1kb)

Failure with incomplete SSL chain

If a server has not been correctly configured to provide the full certificate chain for SSL, then the JCR backend will fail to connect with the error message "unable to verify the first certificate."

Improve network error handling

The SMB Server has does not always handle interruptions in network connectivity well. Consider the following cases:

  • DNS lookup failures impact performance
  • Unexpected network errors while making HTTP requests (i.e. reset connections, refused connections) result in bad application state

To alleviate these issues it's proposed to implement DNS caching and HTTP request retry functionality.

[feature] Support for running in command line globally

Hello, nice project.

It would be great to be able to run it on command line globally. Something like this:

cd /folder/will/be/served
npm install -g node-smb-server
# Running
node-smb-server [another/folder] # optional

folderlisted event enhancements

It would help improve performance in clients if the SMB server included the contents of the listed folder when it emits the folderlisted event. This way the client doesn't need to submit another request to list the contents of the same directory.

I propose adding the list of folders/files in a directory as data on the folderlisted event.

Will Windows support be soon?

I tried out this project using windows (Win10) as client. I managed to pass the authentication by turning off extendedSecurity. But then after login windows immediatly alerts that I can't use the share maybe because I don't have privilege.

Doesn't work on Windows

Followed instructions from the readme, started the server properly.
Entered \\192.168.1.5:8445 in the File Explorer omnibox. Got error

Windows can't find "\\192.168.1.5:8445"

In the Node.js console observed error message

info: [SRV] established client connection #1 from [192.168.1.5:64931] -> [192.168.1.5:8445]
error: [SMB] unsupported NetBIOS session service message type: 79

Disappearing folder contents

The contents for a folder will disappear in Finder if there is a temporary file in the server's target DAM instance. To reproduce:

  • Use the RQ backend
  • Create a "temporary" file in DAM. A good example would be ~SomeTempFile.tmp
  • Start the server and navigate to the directory. Note that the contents of the folder disappear and errors appear in the logs.

Concurrency Issues in RQ Backend

There are various issues caused by concurrency problems in the RQ backend. To reproduce one:

  • Create a directory in DAM with ~50 100-200 KB images. Ensure that files in the directory have not already been cached locally
  • Launch InDesign
  • Connect the SMB server and browse to the new directory
  • Immediately scroll toward the middle of the file list, select a file, and (without releasing the mouse button) drag the file into InDesign
  • Note that the file is corrupt

The root cause of this is that two different "threads" are working on the same image. One thread is downloading the image in order to show the thumbnail. The other thread is reading the file so that it can be placed in InDesign. The "thumbnail" thread begins downloading the file and the "place" thread does a stat on the local file while it is still downloading, resulting in an incorrect size.

The proposed fix is as follows:

  • Add a mechanism that flags a file as "downloading"
  • If a file is flagged as downloading, continue to use the remote file for information like size
  • Whenever a file needs to be read or written, first check to see if the file is flagged as downloading. If so, block until the download is finished; otherwise proceed with the download and set the file's downloading flag

Log improvements

There have been challenges determining the root cause of issues due to limitations in the SMB server's logging. In particular the following have been observed:

  • Error messages without any detail except for vague status codes like STATUS_NO_SUCH_FILE
  • No clear, simple way of observing the HTTP traffic between the server and DAM.

To help with these challenges, it's proposed to:

  • Extend SMBError to allow for more description messages
  • Modify anywhere in backends where non-descriptive error messages are logged; extend these locations to include more detail
  • Pass errors to higher levels so they can be more visible
  • Add a new request.log that logs all requests sent to DAM and the response codes received

ENOENT: no such file or directory, open 'spi.log'

I got this strange error (crash) once, after moving about 2 Gb worth of files. I do think the transfer completed ok, but about 5 minutes after it completed, the node process had crashed. I didn't modify any of the log config. I noticed that in the repo directory there were many .log.gz files (ie. spi.log.gz, gpi1.log.gz, ...., spi9.log.gz )

the only config change i made was to remove all the "non-fs" shares like DAM and JCR and so on, but i doubt that affects the logging.

Running on raspberry pi 4 B (ARM7 ) Raspbian, with node v10.16.0

error: [SMB] encountered unhandled exception at the handler level. exiting message=ENOENT: no such file or directory, open 'spi.log', stack=Error: ENOENT: no such file or directory, open 'spi.log', errno=-2, code=ENOENT, syscall=open, path=spi.log, objectMode=false, highWaterMark=65536, head=null, tail=null, length=0, length=0, 0=0, 1=0, objectMode=false, highWaterMark=16384, head=null, tail=null, length=0, length=0, objectMode=false, highWaterMark=16384, finalCalled=false, needDrain=false, ending=false, ended=false, finished=false, destroyed=false, decodeStrings=true, defaultEncoding=utf8, length=0, writing=false, corked=0, sync=true, bufferProcessing=false, onwrite=function () { [native code] }, writecb=null, writelen=0, bufferedRequest=null, lastBufferedRequest=null, pendingcb=0, prefinished=false, errorEmitted=false, emitClose=false, autoDestroy=false, bufferedRequestCount=0, next=null, entry=null, finish=function () { [native code] }, writable=true, domain=null, removeListener=function updateExceptionCapture() {
  if (stack.every((domain) => domain.listenerCount('error') === 0)) {
    setUncaughtExceptionCaptureCallback(null);
  } else {
    setUncaughtExceptionCaptureCallback(null);
    setUncaughtExceptionCaptureCallback((er) => {
      return process.domain._errorHandler(er);
    });
  }
}, newListener=function updateExceptionCapture() {
  if (stack.every((domain) => domain.listenerCount('error') === 0)) {
    setUncaughtExceptionCaptureCallback(null);
  } else {
    setUncaughtExceptionCaptureCallback(null);
    setUncaughtExceptionCaptureCallback((er) => {
      return process.domain._errorHandler(er);
    });
  }
}, error=function (err) {
          logger.error('encountered unhandled exception at the handler level. exiting', err);
          process.exit(1);
        }, _eventsCount=3, _maxListeners=undefined, members=[], unpipe=function onunpipe(readable, unpipeInfo) {
    debug('onunpipe');
    if (readable === src) {
      if (unpipeInfo && unpipeInfo.hasUnpiped === false) {
        unpipeInfo.hasUnpiped = true;
        cleanup();
      }
    }
  }, drain=function pipeOnDrainFunctionResult() {
    var state = src._readableState;
    debug('pipeOnDrain', state.awaitDrain);
    if (state.awaitDrain)
      state.awaitDrain--;
    if (state.awaitDrain === 0 && EE.listenerCount(src, 'data')) {
      state.flowing = true;
      flow(src);
    }
  }, error=function onerror(er) {
    debug('onerror', er);
    unpipe();
    dest.removeListener('error', onerror);
    if (EE.listenerCount(dest, 'error') === 0)
      errorOrDestroy(dest, er);
  }, close=function () { [native code] }, finish=function () { [native code] }, _eventsCount=5, _maxListeners=undefined, path=spi.log.gz, fd=null, flags=w, mode=438, start=undefined, autoClose=true, pos=undefined, bytesWritten=0, closed=false, pipesCount=1, flowing=true, ended=false, endEmitted=false, reading=true, sync=false, needReadable=true, emittedReadable=false, readableListening=false, resumeScheduled=false, paused=false, emitClose=true, autoDestroy=false, destroyed=false, defaultEncoding=utf8, awaitDrain=0, readingMore=false, decoder=null, encoding=null, readable=true, $ref=$["domainEmitter"]["_readableState"]["pipes"]["_readableState"]["pipes"]["domain"], prefinish=function prefinish() {
  if (typeof this._flush === 'function' && !this._readableState.destroyed) {
    this._flush((er, data) => {
      done(this, er, data);
    });
  } else {
    done(this, null, null);
  }
}, end=[function () { [native code] }, function () { [native code] }], unpipe=function onunpipe(readable, unpipeInfo) {
    debug('onunpipe');
    if (readable === src) {
      if (unpipeInfo && unpipeInfo.hasUnpiped === false) {
        unpipeInfo.hasUnpiped = true;
        cleanup();
      }
    }
  }, drain=function pipeOnDrainFunctionResult() {
    var state = src._readableState;
    debug('pipeOnDrain', state.awaitDrain);
    if (state.awaitDrain)
      state.awaitDrain--;
    if (state.awaitDrain === 0 && EE.listenerCount(src, 'data')) {
      state.flowing = true;
      flow(src);
    }
  }, error=function onerror(er) {
    debug('onerror', er);
    unpipe();
    dest.removeListener('error', onerror);
    if (EE.listenerCount(dest, 'error') === 0)
      errorOrDestroy(dest, er);
  }, close=function () { [native code] }, finish=function () { [native code] }, data=function ondata(chunk) {
    debug('ondata');
    var ret = dest.write(chunk);
    debug('dest.write', ret);
    if (ret === false) {
      // If the user unpiped during `dest.write()`, it is possible
      // to get stuck in a permanently paused state if that write
      // also returned false.
      // => Check whether `dest` is still a piping destination.
      if (((state.pipesCount === 1 && state.pipes === dest) ||
           (state.pipesCount > 1 && state.pipes.indexOf(dest) !== -1)) &&
          !cleanedUp) {
        debug('false write response, pause', state.awaitDrain);
        state.awaitDrain++;
      }
      src.pause();
    }
  }, _eventsCount=8, _maxListeners=undefined, objectMode=false, highWaterMark=16384, finalCalled=false, needDrain=false, ending=false, ended=false, finished=false, destroyed=false, decodeStrings=true, defaultEncoding=utf8, length=0, writing=false, corked=0, sync=true, bufferProcessing=false, onwrite=function () { [native code] }, writecb=null, writelen=0, bufferedRequest=null, lastBufferedRequest=null, pendingcb=0, prefinished=false, errorEmitted=false, emitClose=true, autoDestroy=false, bufferedRequestCount=0, next=null, entry=null, finish=function () { [native code] }, writable=true, allowHalfOpen=true, afterTransform=function () { [native code] }, needTransform=true, transforming=false, writecb=null, writechunk=null, writeencoding=null, _hadError=false, bytesWritten=0, $ref=$["domainEmitter"]["_readableState"]["pipes"]["_readableState"]["pipes"]["domain"], onerror=function zlibOnError(message, errno, code) {
  var self = this[owner_symbol];
  // there is no way to cleanly recover.
  // continuing only obscures problems.
  _close(self);
  self._hadError = true;

  // eslint-disable-next-line no-restricted-syntax
  const error = new Error(message);
  error.errno = errno;
  error.code = code;
  self.emit('error', error);
}, 0=144, 1=123, 2=212, 3=182,  .... [redacted] .... 16383=0, _outOffset=0, _chunkSize=16384, _defaultFlushFlag=0, _finishFlushFlag=4, _nextFlush=-1, _defaultFullFlushFlag=3, _info=undefined, _level=-1, _strategy=0, pipesCount=1, flowing=true, ended=false, endEmitted=false, reading=true, sync=false, needReadable=true, emittedReadable=false, readableListening=false, resumeScheduled=false, paused=false, emitClose=false, autoDestroy=false, destroyed=true, defaultEncoding=utf8, awaitDrain=0, readingMore=false, decoder=null, encoding=null, readable=true, $ref=$["domainEmitter"]["_readableState"]["pipes"]["_readableState"]["pipes"]["domain"], end=[function() {
    if (this.autoClose) {
      this.destroy();
    }
  }, function () { [native code] }], data=function ondata(chunk) {
    debug('ondata');
    var ret = dest.write(chunk);
    debug('dest.write', ret);
    if (ret === false) {
      // If the user unpiped during `dest.write()`, it is possible
      // to get stuck in a permanently paused state if that write
      // also returned false.
      // => Check whether `dest` is still a piping destination.
      if (((state.pipesCount === 1 && state.pipes === dest) ||
           (state.pipesCount > 1 && state.pipes.indexOf(dest) !== -1)) &&
          !cleanedUp) {
        debug('false write response, pause', state.awaitDrain);
        state.awaitDrain++;
      }
      src.pause();
    }
  }, open=[function () { [native code] }, function () { [native code] }], _eventsCount=3, _maxListeners=undefined, path=spi.log, fd=null, flags=r, mode=438, start=undefined, end=Infinity, autoClose=true, pos=undefined, bytesRead=0, closed=false, $ref=$["domainEmitter"]["_readableState"]["pipes"]["_readableState"]["pipes"]["domain"], domainThrown=false
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] start: `node ./index.js`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/pi/.npm/_logs/2019-07-21T01_52_34_516Z-debug.log

Concurrency issues while downloading

In certain cases there is an issue where one SMB cmd may attempt to access a file that another SMB cmd is in the process of downloading. When this happens it manifests as either a corrupt file error or an image that looks incomplete.

To reproduce:

  • Navigate to a directory containing about 10 images
  • Select all the files and drag them onto the Photoshop icon to open them
  • In some cases, observe error messages

Renaming folders does not change DAM UI

When renaming a folder using the RQ backend, the new name is not reflected in the DAM UI. The root cause is that the rename operation updates the node path but does not change the node's jcr:title.

To reproduce:

  • Start the server and mount the RQ backend
  • Open a Finder window and create a new folder
  • Rename the folder
  • Open the target DAM UI. Locate the folder and note that its name is still the old name

Add file download status

Downloading large files from DAM forces most consuming applications into an unresponsive state without any indication that anything is happening, and without any kind of progress notification.

I propose that we extend the RQ backend so that it sends events that indicate download status. We could mirror the existing sync progress events and provide similar notifications for downloads. Consuming applications could use these new notifications to provide feedback to the user.

Issues running server on Windows & Kali

I have run the server on both Windows and Kali, the server starts fine, however, when I attempt to connect to it via smbclient or by mounting a cifs share on Kali, it has errors.

C:\Users\tester\Desktop\smb_test\test\node_modules\node-smb-server>node index.js info: [SRV] logging initialized. info: [SRV] configuration successfully read: C:\Users\tester\Desktop\smb_test\test\node_modules\node-smb-server\config.json info: [SRV] [13220] SMB server started listening on port 8445 info: [SRV] established client connection #1 from [10.3.1.246:54703] -> [10.3.1.246:8445] error: [SRV] uncaught exception: Cannot read property 'negotiateMsg' of undefined TypeError: Cannot read property 'negotiateMsg' of undefined at handle (C:\Users\tester\Desktop\smb_test\test\node_modules\node-smb-server\lib\smb\cmd\session_setup_andx.js:142:15) at C:\Users\tester\Desktop\smb_test\test\node_modules\node-smb-server\lib\smb\handler.js:76:9 at C:\Users\tester\Desktop\smb_test\test\node_modules\async\lib\async.js:181:20 at iterate (C:\Users\tester\Desktop\smb_test\test\node_modules\async\lib\async.js:262:13) at Object.async.forEachOfSeries.async.eachOfSeries (C:\Users\tester\Desktop\smb_test\test\node_modules\async\lib\async.js:281:9) at Object.async.forEachSeries.async.eachSeries (C:\Users\tester\Desktop\smb_test\test\node_modules\async\lib\async.js:214:22) at Object.handleRequest (C:\Users\tester\Desktop\smb_test\test\node_modules\node-smb-server\lib\smb\handler.js:63:9) at C:\Users\tester\Desktop\smb_test\test\node_modules\node-smb-server\lib\smbconnection.js:96:13 at C:\Users\tester\Desktop\smb_test\test\node_modules\async\lib\async.js:181:20 at Object.async.forEachOf.async.eachOf (C:\Users\tester\Desktop\smb_test\test\node_modules\async\lib\async.js:233:13)

I've tried the NPM version and cloning the repo, I get the same error with both versions, same error if I host it on Windows 10 or Kali.

Happy to provide any further information that is needed.

windows client cannot connect

I am using windows 10 to connect to the server.
It failed with error message on the server side:

error: [SMB] unhandled exception while handling request TypeError: Cannot read property 'negotiateMsg' of undefined
at handle (/mnt/sdb/dev/web/opensource/node-smb-server/lib/smb/cmd/session_setup_andx.js:142:15)

Address buffer deprecation warning

➜ npm start

> [email protected] start /Users/maj/src/node-smb-server
> node ./index.js

info: [SRV] logging initialized.
info: [SRV] configuration successfully read: /Users/maj/src/node-smb-server/config.json
(node:9743) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
info: [SRV] [9743] SMB server started listening on port 8445

Would be good to update the code to stop leveraging the deprecated way of using Buffer.

High cpu usage

It's possible for the server to become stuck in a state where it consumes 100% of the CPU. To reproduce:

  • Start the server and connect to a DAM or RQ backend
  • Browse to a directory containing an asset over 256mb large
  • Open the asset
  • Observe that after the asset downloads the server process's CPU usage pegs at 100%

The root cause of the issue is twofold:

  1. The request-retry module introduce an unhandled exception because it forces the request module to load all responses into memory, regardless of whether the response is being streamed. Responses larger than 256mb generate an unhandled exception.
  2. If the server encounters an unhandled exception, it attempts to log the exception, provide an unsuccessful status for the cmd, and continue running. The attempt to provide a status for the cmd was sending the process into an infinite callback loop, thus spiking the cpu. Per NodeJS best practice, the process should exit immediately on unhandled exceptions because the process is not guaranteed to be in a good state after the exception is generated.

Slow performance for large directories

The server becomes very sluggish when dealing with directories that have many children. The listing of the directory's content is slow in itself, and subsequent list requests are very slow as well. Eventually the server becomes overwhelmed and no longer responds to requests in a timely manner. To reproduce:

  • Use the DAM backend
  • Create a directory in DAM and add ~450 subdirectories, each with a small number of files
  • Start the server and browse to the large directory (this was reproduced with Column view in Finder)
  • Attempt to navigate to one of the directory's subfolders
  • Note that the contents don't show up for an unreasonable amount of time

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.