carterapp / exsftpd Goto Github PK
View Code? Open in Web Editor NEWElixir SFTP daemon with customisable user directories
License: Apache License 2.0
Elixir SFTP daemon with customisable user directories
License: Apache License 2.0
This can be done by adding a line
pwdfun: &authenticate_user/4,
to your :ssh initialization,
and a small authentication function
def authenticate_user(ip_address, username, password, state) do
username == 'sftp' and password == 'sftp'
{true,state}
It would be great if you could allow that to be passed in as a configuration option similar to Issue #2 where the library user could pass a module or a function to execute to handle authentication.
I realize there's more too it, defaults and retries and such. I hacked some code in to make it work, but it would be great if the module allowed that natively.
I'm building a service where I would like to accept input via SFTP, so it's not quite the traditional setup where users are expected to drop files into a filesystem. Consequently, I'd like to store public keys somewhere other than on the filesystem. I figure out how to implement username/password authentication against a database table, but I'm having a slower time figuring out how to do so if a key is provided. I looked at the authenticate
option, but that function appears to receive only the username, password, and an options map that contains the source IP.
I see that the underlying erlang library provides :ssh.is_auth_key
for checking keys, and a behavior to allow for customization of the key store. I think I would need to write my own replacement that consulted a different source for those authorized keys. Do you know of anyone else who has set up exsftpd in this manner?
This issue fixed by inserting instead of using into. The warnings were bothering me so I fixed them. You can inspect and both results are the same value and position of :state.
Proposed change
sftpd_channel.ex
defp to_record(record) do
Enum.map(record, fn {_k, v} -> v end) |> List.insert_at(0, :state) |> List.to_tuple()
end
instead of
defp to_record(record) do
IO.inspect(record)
Enum.map(record, fn {_k, v} -> v end) |> Enum.into([:state]) |> List.to_tuple()
end
If you'll take a pull request I'll send one.
traceback -
warning: the Collectable protocol is deprecated for non-empty lists. The behaviour of things like Enum.into/2 or "for" comprehensions with an :into option is incorrect when collecting into non-empty lists. If you're collecting into a non-empty keyword list, consider using Keyword.merge/2 instead. If you're collecting into a non-empty list, consider concatenating the two lists with the ++ operator.
(elixir) lib/collectable.ex:83: Collectable.List.into/1
(elixir) lib/enum.ex:1227: Enum.into_protocol/2
(exsftpd) lib/sftpd_channel.ex:23: Exsftpd.SftpdChannel.to_record/1
(exsftpd) lib/sftpd_channel.ex:73: Exsftpd.SftpdChannel.handle_ssh_msg/2
(ssh) ssh_client_channel.erl:262: :ssh_client_channel.handle_info/2
(stdlib) gen_server.erl:637: :gen_server.try_dispatch/4
(stdlib) gen_server.erl:711: :gen_server.handle_msg/6
(stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
in my config.exs file I spent a while trying to get a custom handler to work here.
event_handler: fn(event) -> IO.puts("Event: #{inspect event} ") end
I changed it to
event_handler: Myapp.Sftp.Events
and
event_handler: Myapp.Sftp.Events.parse
and
event_handler: fn(event) -> Myapp.Sftp.Events.on_event(event) end
(I was surprised the function to function did not work, but I could not get it to work.)
but your code in sftp_file_handler.ex will not execute the varieties I listed, because I cannot pass a function to the config item. If I pass a function, it assumes /0 arrity, and fails to compile as a match.
Line in question-
handler -> handler.({event_name, state[:user], meta})
I modified my local copy like below, you pass a Module, with an Atom of the function.
in config.exs
event_handler: {Myapp.Sftp.Events, :on_event}
in sftp_file_handler.ex
Then you can apply the function like this in the case match above
{handler, function} -> apply(handler, function, [{event_name, state[:user], meta}])
Now, it calls Myapp.Sftp.Events.on_event(event), and is completely user configurable, and easy to read.
I can generate a pull request if you want, or is there some other way this is supposed to work?
I was using your library (thanks!), and needed to support some older legacy SFTP clients using older encryption algorithms that were removed from the default key exchange list in Erlang releases - (reference the release notes (below)).
It was simple to add back the support, basically it adds an option so that users can add to the Erlang parameters, and include a keyword list of parameters.
For example, in my config file here's how I pass in that I want Erlang to allow support for some of these older exchange methods.
config :exsftpd, Exsftpd.Server,
...
modify_algorithms: [
prepend: [kex: [:"diffie-hellman-group1-sha1", :"diffie-hellman-group-exchange-sha1"]],
prepend: [public_key: [:"ssh-rsa", :"ssh-dss"]]
]
Otherwise, it's just an empty list - []
The Erlang documentation around this parameter is here - https://www.erlang.org/docs/23/apps/ssh/configure_algos.html
And the deprecation notices in the release notes are here https://www.erlang.org/docs/23/apps/ssh/notes.html#ssh-4.10
My modification to support this is just about 12 lines added, just a simple parameter to pass through.
Would you be open to a pull request to help build this or a similar way to pass this parameter as a an official feature?
I'm building a service where I would like to accept input via SFTP, so it's not quite the traditional setup where users are expected to drop files into a filesystem. Consequently, I'd like to store public keys somewhere other than on the filesystem. I figure out how to implement username/password authentication against a database table, but I'm having a slower time figuring out how to do so if a key is provided. I looked at the authenticate
option, but that function appears to receive only the username, password, and an options map that contains the source IP.
I see that the underlying erlang library provides :ssh.is_auth_key
which expects to find the authorized public keys in a specific location on the filesystem. I think I would need to write my own replacement that consulted a different source for those authorized keys, but I'm not sure how to get the user-submitted key passed to that function. Do you know of anyone else who has set up exsftpd in this manner?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.