This file is indexed.

/usr/lib/one/ruby/ssh_auth.rb is in opennebula-tools 3.2.1-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# -------------------------------------------------------------------------- #
# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org)             #
#                                                                            #
# Licensed under the Apache License, Version 2.0 (the "License"); you may    #
# not use this file except in compliance with the License. You may obtain    #
# a copy of the License at                                                   #
#                                                                            #
# http://www.apache.org/licenses/LICENSE-2.0                                 #
#                                                                            #
# Unless required by applicable law or agreed to in writing, software        #
# distributed under the License is distributed on an "AS IS" BASIS,          #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
# See the License for the specific language governing permissions and        #
# limitations under the License.                                             #
#--------------------------------------------------------------------------- #


require 'pp'
require 'openssl'
require 'base64'
require 'fileutils'

# SSH key authentication class. It can be used as a driver for auth_mad
# as auth method is defined. It also holds some helper methods to be used
# by oneauth command
class SshAuth
    LOGIN_PATH = ENV['HOME']+'/.one/one_ssh'

    # Initialize SshAuth object
    #
    # @param [Hash] default options for path
    # @option options [String] :public_key public key for the user
    # @option options [String] :private_key key private key for the user.
    def initialize(options={})
        @private_key = nil
        @public_key  = nil

        if options[:private_key]
            begin
                @private_key = File.read(options[:private_key])
            rescue Exception => e
                raise "Cannot read #{options[:private_key]}"
            end
        end

        if options[:public_key]
            @public_key = options[:public_key]
        elsif @private_key != nil
            # Init ssh keys using private key. public key is extracted in a
            # format compatible with openssl. The public key does not contain
            # "---- BEGIN/END RSA PUBLIC KEY ----" and is in a single line
            key = OpenSSL::PKey::RSA.new(@private_key)

            @public_key = key.public_key.to_pem.split("\n")
            @public_key = @public_key.reject {|l| l.match(/RSA PUBLIC KEY/) }.join('')
        end

        if @private_key.nil? && @public_key.nil?
            raise "You have to define at least one of the keys"
        end
    end

    # Creates the login file for ssh authentication at ~/.one/one_ssh.
    # By default it is valid for 1 hour but it can be changed to any number
    # of seconds with expire parameter (in seconds)
    def login(user, expire=3600)
        expire ||= 3600

        # Init proxy file path and creates ~/.one directory if needed
        proxy_dir = File.dirname(LOGIN_PATH)

        begin
            FileUtils.mkdir_p(proxy_dir)
        rescue Errno::EEXIST
        end

        # Generate security token
        time = Time.now.to_i + expire.to_i

        secret_plain   = "#{user}:#{time}"
        secret_crypted = encrypt(secret_plain)

        proxy = "#{user}:#{secret_crypted}"

        file = File.open(LOGIN_PATH, "w")
        file.write(proxy)
        file.close

        File.chmod(0600,LOGIN_PATH)
        
        secret_crypted
    end

    # Returns a valid password string to create a user using this auth driver.
    # In this case the ssh public key.
    def password
        @public_key
    end

    # Checks the proxy created with the login method
    def authenticate(user, token)
        begin
            token_plain = decrypt(token)
            _user, time = token_plain.split(':')

            if user == _user
                if Time.now.to_i >= time.to_i
                    return "ssh proxy expired, login again to renew it"
                else
                    return true
                end
            else
                return "invalid credentials"
            end
        rescue
            return "error"
        end
    end

    private

    ###########################################################################
    #                       Methods to handle ssh keys
    ###########################################################################
    # Encrypts data with the private key of the user and returns
    # base 64 encoded output in a single line
    def encrypt(data)
        rsa=OpenSSL::PKey::RSA.new(@private_key)
        Base64::encode64(rsa.private_encrypt(data)).gsub!(/\n/, '').strip
    end

    # Decrypts base 64 encoded data with pub_key (public key)
    def decrypt(data)
        rsa=OpenSSL::PKey::RSA.new(Base64::decode64(@public_key))
        rsa.public_decrypt(Base64::decode64(data))
    end
end