Giter VIP home page Giter VIP logo

node-samba-client's Introduction

node-samba-client

Node.js wrapper for smbclient

Requirements

Requires Node.js 10+ Smbclient must be installed. This can be installed on Ubuntu with sudo apt-get install smbclient.

API

const SambaClient = require('samba-client');

let client = new SambaClient({
  address: '//server/folder', // required
  username: 'test', // not required, defaults to guest
  password: 'test', // not required
  domain: 'WORKGROUP', // not required
  maxProtocol: 'SMB3', // not required
  maskCmd: true, // not required, defaults to false
});

// send a file
await client.sendFile('somePath/file', 'destinationFolder/name');

// get a file
await client.getFile('someRemotePath/file', 'destinationFolder/name');

// create a folder
await client.mkdir('folder/tree', (optional) 'current/working/directory');
// By default CWD is __dirname

// executes dir command in remote directory
await client.dir('remote/folder', (optional) 'current/working/directory');
// By default CWD is __dirname

// validate if file or folder exists in the remote device
await client.fileExists('remote/file', (optional) 'current/working/directory');
// By default CWD is __dirname

Troubleshooting

Error: spawn ENOTDIR in Electron

Pass an empty string in the Current Working Directory parameter, for more information see this PR.

node-samba-client's People

Contributors

bdelcamp avatar cheng-vang avatar drubetti avatar j-cat avatar jakesjews avatar jcrugzz avatar jmaton avatar nagtechie avatar nhnicwaller avatar olekristensen avatar s0rthak avatar silentroach avatar vasily-polonsky avatar w-raken 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

Watchers

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

node-samba-client's Issues

Add a method to get file contents

I’d like to get contents of a file. I have stumbled upon this SO answer, which works perfectly:

smbclient -E -U $USERNAME //server/sharename $PASSWORD -c 'get \\dir\\file /dev/fd/1'

Could we add a method like readFile()? Subsequently, could we also and an method to writeFile() (different from sendFile() that the contents would be in memory only, not a file)?

UNC path backslashes doubled

The sharing address must have its backslashes doubled. (L'adresse du partage doit obligatoirement avoir ses anti-slashs doublés.)

With Error

const Smb = require('samba-client');
const samba = new Smb({
            'contoso.corp.local',
            'usr12345',
            'P@ssw0rd',
            '\\\\computername\\share'
        });
samba.getFile('file.txt', '/folder/file.txt');
...
\computernameshare: Not enough '\' characters in service
...

Without error

const Smb = require('samba-client');
const samba = new Smb({
            'contoso.corp.local',
            'usr12345',
            'P@ssw0rd',
            '\\\\\\\\computername\\\\\\share'
        });
samba.getFile('file.txt', '/folder/file.txt');

Correction proposal

Change your line 20

- this.address = options.address;
+ this.address = wrap(options.address);

getFile in a remote folder doesn't appear to work

First and foremost, thank you very much for this library! :-)

Consider, the address is: \\theaddress\myshare
Inside that there is a folder named "foo", and in the foo folder there is a file "bar".

I want that file so I do this:

let client = new SambaClient('\\\\theaddress\\myshare, 'myuser', 'mypass', '', 'SMB3');
client.getFile('foo/bar', 'localbar);

This fails with an ENOENT. The command it's running is actually:
smbclient -U 'myuser' -c 'get bar localbar' //theaddress/myshare 'mypass' --max-protocol SMB3

i.e., it strips the folder.

This is due to the code in "runCommand"; it interprets the remote folder as the local working directory:

runCommand(cmd, path, destination) {
    let workingDir = p.dirname(path);
    let fileName = p.basename(path).replace(singleSlash, '\\');
    let cmdArgs = util.format('%s %s', fileName, destination);

    return this.execute(cmd, cmdArgs, workingDir);
  }

I tweaked getFile and sendFile slightly (and deleted runCommand) :

  getFile(path, destination, workingDir) {
    let fileName = path.replace(singleSlash, '\\');
    let cmdArgs = util.format('%s %s', fileName, destination);
    return this.execute('get', cmdArgs, workingDir);
  }

  sendFile(path, destination) {
    let workingDir = p.dirname(path);
    let fileName = p.basename(path).replace(singleSlash, '\\');
    let cmdArgs = util.format('%s %s', fileName, destination.replace(singleSlash, '\\'));
    return this.execute('put', cmdArgs, workingDir);
  }

also in function "execute" I tweaked this line based on the pull request #20

    let options = {
      cwd: (workingDir ? workingDir : '')
    };

May I check in these fixes?

Again, thank you for this library.

Breaking changes in smbclient > 4.12.15-r0

Hi there,

We've experienced some breaking changes in the samba-client apk in alpine > 3.12, where the samba-client version is above 4.12.15-r0

One change that we've located is that a password set in the end of the command does not work, it has to be passed with --password to the smbclient.

Other changes are a bit more hard to debug, and we've resorted to pinning our node:alpine container at alpine3.12 for now.

It seems that smbclient is rather alive and the samba project does not value consistency in the api for it.

I would propose that the readme includes a line about last known version of smbclient that has been tested and found working.

And that we look into where we're at with samba-client version 4.15.2-r0

How can i read files in stream using get method?

Hi,
Thanks for making amazing npm.
I am having spaces in my directory name and file name and when i trying use list method
it is only returning first word of the file not complete name.I think it is a problem with regex
and i am not able to regenerate a perfect regex .
Could you please help me with that?
Thanks
Azam Ahmed

I have strange behavior with sambaClient on Linux SMB share

When I try to connect to Linux SMB share I got error:
ERROR: do_connect: Connection to 192.168.234.223 failed (Error NT_STATUS_IO_TIMEOUT)

const client = new sambaClient({
  address: "//192.168.200.207/exp",
  domain: "LOREANS",
  username: "loran",
  password: "Asd12345",
  maxProtocol: 'SMB3',
  maskCmd: true,
});

But when I connect through smbclient directly trough Linux terminal, everything is fine, and to Windows SMB share is working correctly too

how to fix UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch()

UnhandledPromiseRejectionWarning: Error: Command failed with exit code 1: smbclient -U camera -c put "text.txt" "\Home\20220203" //192.168.0.119/camstorage Cideng99
NT_STATUS_FILE_IS_A_DIRECTORY opening remote file \HomeTazik\20220203
at makeError (/home/cideng87/ServerCamera/node_modules/execa/lib/error.js:60:11)
at handlePromise (/home/cideng87/ServerCamera/node_modules/execa/index.js:118:26)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at async SambaClient.execute (/home/cideng87/ServerCamera/node_modules/samba-client/index.js:160:23)
at async SambaClient.sendFile (/home/cideng87/ServerCamera/node_modules/samba-client/index.js:35:12)
at async sendFileNAS (/home/cideng87/ServerCamera/tes.js:8:18)
(Use node --trace-warnings ... to show where the warning was created)
(node:28442) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:28442) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Path with spaces don't get processed correctly

Wrap the file names and paths with double quotes in runCommand so that they get interpreted correctly. The following worked for me:

runCommand(cmd, path, destination) {
    let workingDir = p.dirname(path);
    let fileName = p.basename(path).replace(singleSlash, '\\');
    let cmdArgs = `"${fileName}" "${destination}"`;

    return this.execute(cmd, cmdArgs, workingDir);
}

File path is stripped out and used in the wrong place

Hey peeps.

Going by the example in readme.md, say I want to get a file from a samba server:

//server/folder/someRemotePath/file

so I do this:

var SambaClient = require('samba-client');
var smb = new SambaClient({
    address: "//server/folder"
});
smb.getFile('someRemotePath/file', '/home/insanity54/Desktop/config.txt', function(err) {
    if (err) console.log(err);
});

Line 81 of index.js strips out the path, leaving just the filename:

var fileName = p.basename(path).replace('/', '\\');
// 'file'

Doesn't the .replace('/', '\\') at that point do nothing, because any slashes were already stripped out by p.basename()? Also, in my testing, replace would only replace the first instance of '/' it found. Anyway that's not the point here.

Separating the path from the filename is all good, but it seems to me that the path doesn't get used in the right place.

Instead of the path being used as the remote directory for smbclient, it's used as the current working directory for smbclient (L70), which isn't going to do any good for retrieving our file on a samba server. You can't simply cd to a samba server, right?

If you don't specify a remote path, this isn't a problem because there is no path to strip away:

smb.getFile('file', ...

But if you specify a remote path, it becomes a problem because the path gets stripped out, and smbclient will look in the root of the smb tree instead of the remote path you specify.

Or am I missing something?

If it's a bug, I'd be happy to submit a pull request.

format of smbclient -c usage appears to be incorrect

Using this library with smbclient 4.13.13-Debian what I see when the fileExists method is an execution of smbclient that looks something like this: smbclient -U username -c dir "test.txt" //host/share password -W domain and the error of test.txt: Not enough '\' characters in service.

My understanding of smbclient is that the whole -c should be wrapped in quotes. i.e. this library should generate a command that looks like this: smbclient -U username -c "dir test.txt" //host/share password -W domain when fileExists('test.txt') is called.

Additional example: if -c is moved to the end of the command i.e. smbclient -U username //host/share password -W domain -c dir "test.txt" what you'll see is a dir of the entire directory.

In my usage, my client config looks like:

let client = new SambaClient({
  address: '//server/folder',
  username: 'test', 
  password: 'test',
  domain: 'WORKGROUP', 
  maskCmd: false,
});

`Error: STATUS_ACCESS_DENIED (0xC0000022)` Despite Full Control Permissions

Description:

I am encountering an issue where the rmdir and unlink methods return a STATUS_ACCESS_DENIED (0xC0000022) error, even though the user has been verified to have Full Control Permissions.

Environment:

  • Library Version: [0.2.11]
  • Node Version: [16.17.1]
  • Operating System: [Windows10]

Code:

Here is how I initialize the SMB2 client with anonymized sensitive information:

const smb2Client = new SMB2({
  share: '[Your Share Path]',
  domain: '[Your Domain]',
  username: '[Anonymized Username]',
  password: '[Anonymized Password]',
  autoCloseTimeout: 0
});

Steps to Reproduce:

  1. Initialize the SMB2 client with the appropriate credentials having Full Control Permissions.
  2. Attempt to execute rmdir or unlink methods on the share.

Actual Results:

The library returns a STATUS_ACCESS_DENIED (0xC0000022) error, indicating a lack of permission to perform the operation.

Expected Results:

Given the user has Full Control Permissions, the rmdir and unlink operations should be executed successfully without any errors related to access denial.

Additional Information:

  • The permissions for the user account have been verified, and it undeniably possesses Full Control Permissions over the share.
  • The shared path and domain provided in the initialization are correct.
  • Every other method including exists, rename, readFile, writeFile, readdir, and mkdir operates successfully, presenting issues only with rmdir and unlink.
  • Here are the relevant debug logs:
--request
smb2-forge.js:96 fe534d42400000000000000005007e0000000000000000001200000000000000c4a187006071d25ac719cb130000000000000000000000000000000000000000390000000200000000000000000000000000000000000000df011700000000000700000001000000200000007800160090000000000000006e006f00640065006a0073001b52fa5e8476ee76555f0042
smb2-forge.js:64 --response
smb2-forge.js:65 fe534d42400000000000000005007e0001000000000000001200000000000000c4a187006071d25ac719cb1300000000000000000000000000000000000000005900000001000000f42500da22f1d901d35456eb22f1d901f42500da22f1d901f42500da22f1d90100000000000000000000000000000000100000000000000009b124e5000000005eed9f57000000000000000000000000
smb2-forge.js:95 --request
smb2-forge.js:96 fe534d42400000000000000006007e0000000000000000001300000000000000c4a187006071d25ac719cb130000000000000000000000000000000000000000180000000000000009b124e5000000005eed9f5700000000
smb2-forge.js:64 --response
smb2-forge.js:65 fe534d42400000000000000006007e0001000000000000001300000000000000c4a187006071d25ac719cb1300000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
smb2-forge.js:95 --request
smb2-forge.js:96 fe534d42400000000000000005007e0000000000000000001400000000000000c4a187006071d25ac719cb13000000000000000000000000000000000000000039000000020000000000000000000000000000000000000081001000000000000700000001000000210020007800160090000000000000006e006f00640065006a0073001b52fa5e8476ee76555f0042
smb2-forge.js:64 --response
smb2-forge.js:65 fe534d42400000000000000005007e0001000000000000001400000000000000c4a187006071d25ac719cb1300000000000000000000000000000000000000005900000001000000f42500da22f1d901d35456eb22f1d901f42500da22f1d901f42500da22f1d9010000000000000000000000000000000010000000000000009c28e1f6000000008caa8441000000000000000000000000
smb2-forge.js:95 --request
smb2-forge.js:96 fe534d42400000000000000011007e0000000000000000001500000000000000c4a187006071d25ac719cb1300000000000000000000000000000000000000002100010d0100000060000000000000009c28e1f6000000008caa84410000000001
smb2-forge.js:64 --response
smb2-forge.js:65 fe534d4240000000220000c011007e0001000000000000001500000000000000c4a187006071d25ac719cb130000000000000000000000000000000000000000090000000000000000
samba.js:136 Error during directory deletion process: Error: STATUS_ACCESS_DENIED (0xC0000022) : {Access Denied} A process has requested access to an object but has not been granted those access rights.
    at Object.eval (message.js:25:21)
    at Socket.eval (smb2-forge.js:72:31)
    at Socket.emit (VM24 node:events:513:28)
    at addChunk (VM66 readable:315:12)
    at readableAddChunk (VM66 readable:289:9)
    at Readable.push (VM66 readable:228:10)
    at TCP.onStreamRead (VM51 stream_base_commons:190:23)

I am seeking guidance or advice on how to rectify this discrepancy. Is this indicative of a potential bug in the library, or is there an aspect I might be overlooking? Any assistance or insights provided would be highly valued.

Getting Command failed with ENONENT with smbclient function on AWS

Hi,

I am trying to use this library for one of my POC. and its under serverless function written in typescript with . node version thsi functionis using with 14.15.0

and floowing are smbclient version

"samba-client": "^5.0.2",
"smbclient": "^1.0.3"

this function when invoked locally its abel to acess fsx file system, but when i deploy this function on aws and test it , it gives an error "Command failed with ENONENT" all the vpc and security groups seems to be working , as other lambada's are able to connect to the FSX using same vpc config are working ok

Please, can someone point me in right direction in case i missing something?

Thanks
Nitin

Add option to mask command

Hi,

It is possible to add an option to hide the command information in case of errors thrown?

In the execute method, right now if there is an error, due to the way node child_process.exec works, the library returns the full command plus whatever was in stdout/stderr. This can be a security risk as the full command would contain the password as well.

execute(cmd, cmdArgs, workingDir) {
    const fullCmd = wrap(util.format("%s %s", cmd, cmdArgs));
    const command = [
      "smbclient",
      this.getSmbClientArgs(fullCmd).join(" "),
    ].join(" ");

    const options = {
      cwd: workingDir || "",
    };

    return new Promise((resolve, reject) => {
      exec(command, options, function (err, stdout, stderr) {
        const allOutput = stdout + stderr;

        if (err) {
          err.message += allOutput;
          return reject(err); // Has information about the full command
        }

        return resolve(allOutput);
      });
    });
  }

I'll be happy to contribute a pull request to add maskCmd as an additional option and if it is set to true, only return the stdout/stderr output instead of the whole command.

Let me know, thanks!

Is there a way I can change the password of a user using this library?

I want to be able to change the password of a user using samba-client. But I can't see a method in this library that I can use to do that.

My main goal is to change the password of a user in a LDAP server. I can do this using a Linux script and running samba-client command smbpasswd, but I need to do it in node.js.

write streams?

Hi guys

its not clear to me from the documentation if there is possibility for creating write streams using this library?

Can't specify version of SMB protocol

When I try using this wrapper for smbclient, I get this error no matter what I do:

protocol negotiation failed: NT_STATUS_CONNECTION_DISCONNECTED

It looks like this is a known issue between some versions of smbclient and SMB servers when using the latest protocol SMB3_11.

Workaround

I'm able to work around the issue by adding an extra option -m SMB3_10 to the invocation on the command line. But there doesn't seem to be any way to add that option using this wrapper, so it seems that I'm unable to use this wrapper.

Additional info

$ smbclient --version
Version 4.5.16-Debian
$ cat /etc/issue
Debian GNU/Linux 9 \n \l

Docker base image: node:10.19.0

SMB Server OS: Windows 10 Pro, Version 1909, OS Build 18363.657

`getFile` does not handle destination correctly

When calling getFile with a destination that is an absolute path (or more generally, with a path including /) the file is incorrectly stored locally.

The cause of the issue is the replacement of / with \\ in getCleanedSmbClientArgs for the destination argument.

I think this can be somewhat avoided by using the workingDir option, but strictly speaking the destination argument should be exempt from that sort of path modification.

Fails when run as cron task with `smbclient: command not found` message

Hi

I have a Node script that works perfectly fine when I run it from the command line.
When I try to run it as a cron command with
*/15 * * * * cd /home/path/to/local/script && node index.js >> /home/path/to/my/log.log 2>&1
I get the following error

Error: Command failed: smbclient -U 'myuser' -c 'dir "path\to\remote\"' {rest of sensitive info removed}
/bin/sh: smbclient: command not found
/bin/sh: smbclient: command not found

    at ChildProcess.exithandler (child_process.js:303:12)
    at ChildProcess.emit (events.js:315:20)
    at maybeClose (internal/child_process.js:1021:16)
    at Socket.<anonymous> (internal/child_process.js:443:11)
    at Socket.emit (events.js:315:20)
    at Pipe.<anonymous> (net.js:674:12) {
  killed: false,
  code: 127,
  signal: null,
  cmd: `smbclient -U 'myuser' -c 'dir "path\to\remote\"' {rest of sensitive info removed}`
}

When I manually run the full command given in the above last line, all works fine.
It's just when I run my script as a cron task. Any idea why it's failing?

Please note, I have other methods in this script that work just fine. It's just the smbclient that seems have issues.

Adding typescript definitions

Hi again!

I was wondering if it's possible to add a typescript definition file in the project.
I'm using this package on a project and have written typings for some of the functions.

Would be happy to complete them if it's possible to add them to this project (an extra index.d.ts file I think) or could even contribute them to @DefinitelyTyped

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.