eterry1388 / pritunl_api_client

API client for Pritunl written in Ruby
MIT License
14 stars 6 forks source link

RestClient::Unauthorized (401 Unauthorized) for about half of the resources #1

Open nielsbuus opened 5 years ago

nielsbuus commented 5 years ago

After exploring this gem for a while, I encountered some issues. I'm not down with the internals of Pritunl Enterprise, so I'm not sure if the gem or the server is to blame.

Anyway, if I list organizations, I get a response. If I list users for an organization id, I get a response. But if I try to create a user, I get a:

RestClient::Unauthorized (401 Unauthorized)

Here is the output from RestClient

RestClient.post "https://pritunl-dev-test.***.**/user/5c0ae40011a33c0bae961789", "{\"name\": \"Joe\"}", "Accept"=>"application/json", "Accept-Encoding"=>"gzip, deflate", "Auth-Nonce"=>"7a7f5dda2dac4bc0f5b9ce1282572aef", "Auth-Signature"=>"iNb4RArLI0QzVtZRxkOKZPfFwaC1+zFkbeJnTSiXkUs=", "Auth-Timestamp"=>"1548264077", "Auth-Token"=>"cG7DU75l6ODlVBDfl5y3W0Lo0VkTEAcL", "Content-Length"=>"15", "Content-Type"=>"application/json", "User-Agent"=>"rest-client/2.0.2 (darwin18.2.0 x86_64) ruby/2.5.1p57"

I have taken a look at https://github.com/pritunl/pritunl/blob/master/pritunl/handlers/user.py and it doesn't seem to make any distinction between the different resources. All of them are decorated with @auth.session_auth.

My only suspect is these conditions if settings.app.demo_mode:, but there is nothing indicating any "demo mode" being activated. I've checked the MongoDB app document in the settings collection and nothing. And even if it was the case, the code here implies that I should get a 400, not 401: https://github.com/pritunl/pritunl/blob/533fb5ea2b2a60dfb75103bfd19ed121302409c7/pritunl/utils/json_helpers.py#L54

Any clues?

nielsbuus commented 5 years ago

Update:

I have narrowed the issue on the server-side down to this method:

https://github.com/pritunl/pritunl/blob/305e5cffb32c568eb1e278c742470139c7eef6f9/pritunl/auth/administrator.py#L333

However, I haven't figured out whether the method contains a bug or pritunl_api_client contains a bug.

Also, I don't know why it only affects some resources. I thought it might be verb-specific, but I get a 401 when loading the events resource using GET.

Update:

Problem seems to happen here: https://github.com/pritunl/pritunl/blob/305e5cffb32c568eb1e278c742470139c7eef6f9/pritunl/auth/administrator.py#L372

Asiderr commented 5 years ago

@nielsbuus Did you find a solution for this bug?

nielsbuus commented 5 years ago

Yes, sorry. I should have updated this issue.

I made a monkey patch.

# In the official version of Pritunl client (2.0.0), params are appended to the auth_string. But the server side does not include params, leading to invalid signatures on POST requests.

module PritunlApiClient

  class Api

    def generate_auth_headers( path:, params: nil, method: )
      auth_timestamp = Time.now.to_i
      auth_nonce = SecureRandom.hex( 16 )
      auth_string = [@api_token, auth_timestamp, auth_nonce, method, path]
      auth_string = auth_string.join( '&' )
      digest = OpenSSL::Digest.new( 'sha256' )
      hmac = OpenSSL::HMAC.digest( digest, @api_secret, auth_string )
      auth_signature = Base64.encode64( hmac ).chomp
      {
          auth_token:     @api_token,
          auth_timestamp: auth_timestamp,
          auth_nonce:     auth_nonce,
          auth_signature: auth_signature
      }
    end

  end
end