Skip to content

Commit

Permalink
Added support for crypt and plaintext authentication.
Browse files Browse the repository at this point in the history
Modified tests and code to fully support ruby 1.8.7, too.
Tests can now be run via rake, as well.

Update readme to reflection that authentication works now.

Renaming to get the markdown goodness.

Adding rbx-require-relative to get the desired behaviors for require_relative when running on ruby 1.8.7. This ruby version is listed a supported platform in .travis.yml.

Making both gem and tests happy on Ruby 1.8.7.

Throwing in some tests that should allow testing of plain and crypt auth scenarios.

Key did not get parsed on ruby 1.8.x because ruby 1.8.x is stupid. But sure, preserving compatibility.
  • Loading branch information
smartperson committed May 12, 2015
1 parent 37a84c0 commit eb47d79
Show file tree
Hide file tree
Showing 15 changed files with 147 additions and 51 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ source 'https://rubygems.org'
gem 'hoe'
gem 'rspec'
gem 'rake'
gem 'rbx-require-relative', :platforms => :ruby_18
2 changes: 2 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ GEM
hoe (3.12.0)
rake (>= 0.8, < 11.0)
rake (10.3.2)
rbx-require-relative (0.0.9)
rspec (3.0.0)
rspec-core (~> 3.0.0)
rspec-expectations (~> 3.0.0)
Expand All @@ -24,4 +25,5 @@ PLATFORMS
DEPENDENCIES
hoe
rake
rbx-require-relative
rspec
1 change: 0 additions & 1 deletion README.txt → README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ Cons:

Implements

* Authentification
* Original test

Spec
Expand Down
6 changes: 5 additions & 1 deletion Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@ $:.unshift(File.dirname(__FILE__)+"/lib")
require 'rubygems'
require 'rserve'
require 'rspec'
require 'rspec/core/rake_task'
begin
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec)
rescue LoadError
end
# vim: syntax=ruby
4 changes: 4 additions & 0 deletions data/Rserv-cryptonly.conf.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
port 6313
auth required
plaintext disable
remote enable
4 changes: 4 additions & 0 deletions data/Rserv-plaintext.conf.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
port 6312
auth required
plaintext enable
remote enable
1 change: 1 addition & 0 deletions data/Rserv.passwords
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test password
27 changes: 14 additions & 13 deletions lib/rserve.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,22 @@ module Rserve
end

require 'spoon' if RUBY_PLATFORM == "java"
require 'require_relative' if RUBY_VERSION < "1.9"

require 'rserve/withnames'
require 'rserve/withattributes'
require 'rserve/with2dnames'
require 'rserve/with2dsizes'
require_relative 'rserve/withnames'
require_relative 'rserve/withattributes'
require_relative 'rserve/with2dnames'
require_relative 'rserve/with2dsizes'


require 'rserve/protocol'
require 'rserve/packet'
require 'rserve/talk'
require 'rserve/rexp'
require 'rserve/engine'
require 'rserve/session'
require 'rserve/connection'
require 'rserve/rlist'
require 'rserve/rfactor'
require_relative 'rserve/protocol'
require_relative 'rserve/packet'
require_relative 'rserve/talk'
require_relative 'rserve/rexp'
require_relative 'rserve/engine'
require_relative 'rserve/session'
require_relative 'rserve/connection'
require_relative 'rserve/rlist'
require_relative 'rserve/rfactor'


38 changes: 23 additions & 15 deletions lib/rserve/connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class Connection < Rserve::Engine
IncorrectServerError=Class.new(StandardError)
IncorrectServerVersionError=Class.new(StandardError)
IncorrectProtocolError=Class.new(StandardError)
IncorrectCredentialsError=Class.new(StandardError)
NotConnectedError=Class.new(StandardError)
# Eval error
class EvalError < RuntimeError
Expand Down Expand Up @@ -41,12 +42,14 @@ def initialize(rp)
# You could provide a hash with options. Options are analog to java client:
# [+:auth_req+] If authentification is required (false by default)
# [+:transfer_charset+] Transfer charset ("UTF-8" by default)
# [+:auth_type+] Type of authentification (AT_plain by default)
# [+:auth_type+] Type of authentication (AT_plain by default)
# [+:hostname+] Hostname of Rserve ("127.0.0.1" by default)
# [+:port_number+] Port Number of Rserve (6311 by default)
# [+:max_tries+] Maximum number of tries before give up (5 by default)
# [+:cmd_init+] Command to init Rserve if not initialized ("R CMD Rserve" by default)
# [+:proc_rserve_ok+] Proc testing if Rserve works (uses system by default)
# [+:cmd_init+] Command to init Rserve if not initialized ("R CMD Rserve" by default)
# [+:proc_rserve_ok+] Proc testing if Rserve works (uses system by default)
# [+:username+] Username to use (if authentication is required)
# [+:password+] Password to use (if authentication is required)
def initialize(opts=Hash.new)
@auth_req = opts.delete(:auth_req) || false
@transfer_charset = opts.delete(:transfer_charset) || "UTF-8"
Expand All @@ -56,6 +59,8 @@ def initialize(opts=Hash.new)
@max_tries = opts.delete(:max_tries) || 5
@cmd_init = opts.delete(:cmd_init) || "R CMD Rserve"
@proc_rserve_ok = opts.delete(:proc_rserve_ok) || lambda { system "killall -s 0 Rserve" }
@username = opts.delete(:username) || nil
@password = opts.delete(:password) || nil
@session = opts.delete(:session) || nil
@tries = 0
@connected=false
Expand Down Expand Up @@ -115,20 +120,15 @@ def connect
(3..7).each do |i|
attr=input[i]
if (attr=="ARpt")
if (!auth_req) # this method is only fallback when no other was specified
auth_req=true
auth_type=AT_plain
end
end
if (attr=="ARuc")
auth_req=true
authType=AT_crypt
end
if (attr[0]=='K')
key=attr[1,3]
@auth_req=true
elsif (attr=="ARuc")
@auth_req=true
@auth_type=AT_crypt #
elsif (attr[0..0]=='K')
@key=attr[1,2]
end

end
login if auth_req
else # we have a session to take care of
@s.write(@session.key.pack("C*"))
@rsrv_version=session.rsrv_version
Expand All @@ -143,6 +143,14 @@ def connected?
@connected
end

# This server requires a login. Send the required credentials to the server.
def login
raise IncorrectCredentialsError, "Need username and password to connect" if @username.nil? || @password.nil?
@password = @password.crypt(key) if key && auth_type == AT_crypt
rp = @rt.request({:cmd => Rserve::Protocol::CMD_login, :cont => "#{@username}\n#{@password}"})
raise IncorrectCredentialsError, "Server did not accept credentials" if rp.error?
end

# Closes current connection
def close
if !@s.nil? and !@s.closed?
Expand Down
1 change: 1 addition & 0 deletions lib/rserve/packet.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class Packet
ERROR_DESCRIPTIONS={
2=>'Invalid expression',
3=>'Parse error',
65=>'Login error',
127=>'Unknown variable/method'}

def initialize(cmd, cont)
Expand Down
2 changes: 1 addition & 1 deletion lib/rserve/protocol.rb
Original file line number Diff line number Diff line change
Expand Up @@ -230,4 +230,4 @@ def set_long(l, buf, o)
end
end

require 'rserve/protocol/rexpfactory'
require_relative 'protocol/rexpfactory'
38 changes: 19 additions & 19 deletions lib/rserve/rexp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -424,32 +424,32 @@ def to_ruby_internal
end


require 'rserve/rexp/environment'
require 'rserve/rexp/null'
require 'rserve/rexp/unknown'
require_relative 'rexp/environment'
require_relative 'rexp/null'
require_relative 'rexp/unknown'


require 'rserve/rexp/vector'
require_relative 'rexp/vector'

require 'rserve/rexp/raw'
require 'rserve/rexp/symbol'
require 'rserve/rexp/string'
require 'rserve/rexp/double'
require 'rserve/rexp/integer'
require 'rserve/rexp/logical'
require_relative 'rexp/raw'
require_relative 'rexp/symbol'
require_relative 'rexp/string'
require_relative 'rexp/double'
require_relative 'rexp/integer'
require_relative 'rexp/logical'

require 'rserve/rexp/factor'
require_relative 'rexp/factor'

require 'rserve/rexp/genericvector'
require 'rserve/rexp/expressionvector'
require_relative 'rexp/genericvector'
require_relative 'rexp/expressionvector'


require 'rserve/rexp/list'
require 'rserve/rexp/language'
require 'rserve/rexp/s4'
require_relative 'rexp/list'
require_relative 'rexp/language'
require_relative 'rexp/s4'

require 'rserve/rexp/reference'
require_relative 'rexp/reference'

require 'rserve/rexp/wrapper'
require 'rserve/rexp/function'
require_relative 'rexp/wrapper'
require_relative 'rexp/function'

70 changes: 70 additions & 0 deletions spec/rserve_connection_authentication_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
require File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb")
require 'tempfile'

describe Rserve::Connection do
before(:all) do
lambda { system "killall Rserve" }.call #clean up any extra Rserves
password_file = File.expand_path("./data/Rserv.passwords")

plain_config = IO.read('./data/Rserv-plaintext.conf.example')
plain_config = plain_config + "\npwdfile #{password_file}\n"
@plain_config_file = Tempfile.new('Rserv-plaintext.conf')
@plain_config_file.write(plain_config)
@plain_config_file.flush
crypt_config = IO.read('./data/Rserv-cryptonly.conf.example')
crypt_config = crypt_config + "\npwdfile #{password_file}\n"
@crypt_config_file = Tempfile.new('Rserv-cryptonly.conf')
@crypt_config_file.write(crypt_config)
@crypt_config_file.flush
end
describe "opening and closing plaintext" do
before(:all) do
@r=Rserve::Connection.new(:cmd_init => "R CMD Rserve --RS-conf #{@plain_config_file.path}", :username => "test", :password => "password", :port_number => 6312)
end
it "should be open a connection and receive ID-String" do
@r.get_server_version.should==103
@r.protocol.should=="QAP1"
@r.last_error.should=="OK"
@r.rt.should be_instance_of(Rserve::Talk)
end
it "should eval something properly" do
@r.void_eval("x<-1").should be true
end
it "should shut down correctly" do
@r.should be_connected
@r.close.should be true
@r.should_not be_connected
end
end
describe "opening and closing plaintext wrong password" do
it "should fail to connect" do
expect {@r=Rserve::Connection.new(:cmd_init => "R CMD Rserve --RS-conf #{@plain_config_file.path}", :username => "test", :password => "wrongpassword", :port_number => 6312)}.to raise_error(Rserve::Connection::IncorrectCredentialsError)
lambda { system "killall Rserve" }.call #clean up any extra Rserves
end
end
describe "opening and closing crypt" do
before(:all) do
@r=Rserve::Connection.new(:cmd_init => "R CMD Rserve --RS-conf #{@crypt_config_file.path}", :username => "test", :password => "password", :port_number => 6313)
end
it "should be open a connection and receive ID-String" do
@r.get_server_version.should==103
@r.protocol.should=="QAP1"
@r.last_error.should=="OK"
@r.rt.should be_instance_of(Rserve::Talk)
end
it "should eval something properly" do
@r.void_eval("x<-1").should be true
end
it "should shut down correctly" do
@r.should be_connected
@r.close.should be true
@r.should_not be_connected
end
end
describe "opening and closing crypt wrong password" do
it "should fail to connect" do
expect {@r=Rserve::Connection.new(:cmd_init => "R CMD Rserve --RS-conf #{@crypt_config_file.path}", :username => "test", :password => "wrongpassword", :port_number => 6313)}.to raise_error(Rserve::Connection::IncorrectCredentialsError)
lambda { system "killall Rserve" }.call #clean up any extra Rserves
end
end
end
2 changes: 1 addition & 1 deletion spec/rserve_connection_on_unix_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
describe "Rserve::Connection on unix" do
if !Rserve::ON_WINDOWS
before do
@r=Rserve::Connection.new
@r=Rserve::Connection.new
end
after do
@r.close if @r.connected?
Expand Down
1 change: 1 addition & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
require 'matrix'
require 'pp'

INFINITY = +1.0/0.0 if RUBY_VERSION < "1.9"

RSpec.configure do |config|
config.expect_with :rspec do |c|
Expand Down

0 comments on commit eb47d79

Please sign in to comment.