rugged icon indicating copy to clipboard operation
rugged copied to clipboard

Invalid credentials result in infinite loop

Open cschlack opened this issue 9 years ago • 2 comments

credentials = Rugged::Credentials::UserPassword.new({ username: 'user', password: 'abcd' })
repository = Rugged::Repository.clone_at('https://github.com/libgit2/private_repository',
                                         'repository_clone/',
                                         { credentials: credentials })

results in an infinite loop.

According to https://github.com/libgit2/libgit2/issues/3358 and https://libgit2.github.com/libgit2/#HEAD/group/callback/git_cred_acquire_cb

git_cred_acquire_cb() is supposed to return GIT_EAUTH in case of invalid credentials, otherwise the callback will be called indefinitely.

Since username and password are static in this example, the callback returns GIT_OK (https://github.com/libgit2/rugged/blob/884f3672460c50a5cabfbcbe6b760e7070076a18/ext/rugged/rugged_remote.c#L155) and we're caught in the callback loop.

cschlack avatar Apr 22 '16 14:04 cschlack

~~fixed with #596~~

cschlack avatar Jan 12 '17 12:01 cschlack

@cschlack I think rugged uses the callback paradigm for credentials, so that you can hook it into a UI and keep asking the user for userid/password in case he enters an invalid one. From a UI perspective if the user hits cancel after several attempts it can raise its own error which rugged will propagate back to you.

I have a small script that I used with callbacks that sets the password once via a callback and on the next call it raises an exception. This sample uses a global variable but you could use an instance variable and achieve the same thing.

require 'rugged'

def self_signed(valid, host) 
  true
end

$credentials_set = false
def credentials(url, username, allowed_types)
  raise "Invalid credentials" if $credentials_set
  $credentials_set = true
  Rugged::Credentials::UserPassword.new(:username => "root", :password => "secret")
end

options = {:remote             => 'origin',
           :credentials        => method(:credentials),
           :certificate_check  => method(:self_signed)}
begin
  Rugged::Repository.clone_at("https://a.b.c", "/tmp/dir", options)
rescue Rugged => e
  puts e.message
end

mkanoor avatar Apr 21 '17 22:04 mkanoor