def create_ssh_tunnel(self, tunnel_password): """ This method is used to create ssh tunnel and update the IP Address and IP Address and port to localhost and the local bind port return by the SSHTunnelForwarder class. :return: True if tunnel is successfully created else error message. """ # Fetch Logged in User Details. user = User.query.filter_by(id=current_user.id).first() if user is None: return False, gettext("Unauthorized request.") if tunnel_password is not None and tunnel_password != '': crypt_key_present, crypt_key = get_crypt_key() if not crypt_key_present: raise CryptKeyMissing() try: tunnel_password = decrypt(tunnel_password, crypt_key) # Handling of non ascii password (Python2) if hasattr(str, 'decode'): tunnel_password = \ tunnel_password.decode('utf-8').encode('utf-8') # password is in bytes, for python3 we need it in string elif isinstance(tunnel_password, bytes): tunnel_password = tunnel_password.decode() except Exception as e: current_app.logger.exception(e) return False, "Failed to decrypt the SSH tunnel " \ "password.\nError: {0}".format(str(e)) try: # If authentication method is 1 then it uses identity file # and password if self.tunnel_authentication == 1: self.tunnel_object = SSHTunnelForwarder( (self.tunnel_host, int(self.tunnel_port)), ssh_username=self.tunnel_username, ssh_pkey=get_complete_file_path(self.tunnel_identity_file), ssh_private_key_password=tunnel_password, remote_bind_address=(self.host, self.port)) else: self.tunnel_object = SSHTunnelForwarder( (self.tunnel_host, int(self.tunnel_port)), ssh_username=self.tunnel_username, ssh_password=tunnel_password, remote_bind_address=(self.host, self.port)) self.tunnel_object.start() self.tunnel_created = True except BaseSSHTunnelForwarderError as e: current_app.logger.exception(e) return False, "Failed to create the SSH tunnel." \ "\nError: {0}".format(str(e)) # Update the port to communicate locally self.local_bind_port = self.tunnel_object.local_bind_port return True, None
def reset_master_password(): """ Removes the master password and remove all saved passwords This password will be used to encrypt/decrypt saved server passwords """ cleanup_master_password() return make_json_response(data=get_crypt_key()[0])
def export_password_env(self, env): if self.password: crypt_key_present, crypt_key = get_crypt_key() if not crypt_key_present: return False, crypt_key password = decrypt(self.password, crypt_key).decode() os.environ[str(env)] = password
def change_password(): """View function which handles a change password request.""" has_error = False form_class = _security.change_password_form if request.json: form = form_class(MultiDict(request.json)) else: form = form_class() if form.validate_on_submit(): try: change_user_password(current_user._get_current_object(), form.new_password.data) except SOCKETErrorException as e: # Handle socket errors which are not covered by SMTPExceptions. logging.exception(str(e), exc_info=True) flash(gettext(SMTP_SOCKET_ERROR).format(e), 'danger') has_error = True except (SMTPConnectError, SMTPResponseException, SMTPServerDisconnected, SMTPDataError, SMTPHeloError, SMTPException, SMTPAuthenticationError, SMTPSenderRefused, SMTPRecipientsRefused) as e: # Handle smtp specific exceptions. logging.exception(str(e), exc_info=True) flash(gettext(SMTP_ERROR).format(e), 'danger') has_error = True except Exception as e: # Handle other exceptions. logging.exception(str(e), exc_info=True) flash(gettext(PASS_ERROR).format(e), 'danger') has_error = True if request.json is None and not has_error: after_this_request(view_commit) do_flash(*get_message('PASSWORD_CHANGE')) old_key = get_crypt_key()[1] set_crypt_key(form.new_password.data, False) from pgadmin.browser.server_groups.servers.utils \ import reencrpyt_server_passwords reencrpyt_server_passwords(current_user.id, old_key, form.new_password.data) return redirect( get_url(_security.post_change_view) or get_url(_security.post_login_view)) if request.json and not has_error: form.user = current_user return default_render_json(form) return _security.render_template( config_value('CHANGE_PASSWORD_TEMPLATE'), change_password_form=form, **_ctx('change_password'))
def set_master_password(): """ Set the master password and store in the memory This password will be used to encrypt/decrypt saved server passwords """ data = None if hasattr(request.data, 'decode'): data = request.data.decode('utf-8') if data != '': data = json.loads(data) # Master password is not applicable for server mode if not config.SERVER_MODE and config.MASTER_PASSWORD_REQUIRED: # if master pass is set previously if current_user.masterpass_check is not None and \ data.get('button_click') and \ not validate_master_password(data.get('password')): return form_master_password_response( existing=True, present=False, errmsg=gettext("Incorrect master password")) if data != '' and data.get('password', '') != '': # store the master pass in the memory set_crypt_key(data.get('password')) if current_user.masterpass_check is None: # master check is not set, which means the server password # data is old and is encrypted with old key # Re-encrypt with new key from pgadmin.browser.server_groups.servers.utils \ import reencrpyt_server_passwords reencrpyt_server_passwords(current_user.id, current_user.password, data.get('password')) # set the encrypted sample text with the new # master pass set_masterpass_check_text(data.get('password')) elif not get_crypt_key()[0] and \ current_user.masterpass_check is not None: return form_master_password_response( existing=True, present=False, ) elif not get_crypt_key()[0]: error_message = None if data.get('button_click') and data.get('password') == '': # If user attempted to enter a blank password, then throw error error_message = gettext("Master password cannot be empty") return form_master_password_response(existing=False, present=False, errmsg=error_message) # if master password is disabled now, but was used once then # remove all the saved passwords process_masterpass_disabled() if config.SERVER_MODE and current_user.masterpass_check is None: crypt_key = get_crypt_key()[1] from pgadmin.browser.server_groups.servers.utils \ import reencrpyt_server_passwords reencrpyt_server_passwords(current_user.id, current_user.password, crypt_key) set_masterpass_check_text(crypt_key) return form_master_password_response(present=True, )
def check_master_password(): """ Checks if the master password is available in the memory This password will be used to encrypt/decrypt saved server passwords """ return make_json_response(data=get_crypt_key()[0])
def connection(self, database=None, conn_id=None, auto_reconnect=True, did=None, async_=None, use_binary_placeholder=False, array_to_string=False): if database is not None: if hasattr(str, 'decode') and \ not isinstance(database, unicode): database = database.decode('utf-8') if did is not None: if did in self.db_info: self.db_info[did]['datname'] = database else: if did is None: database = self.db elif did in self.db_info: database = self.db_info[did]['datname'] else: maintenance_db_id = u'DB:{0}'.format(self.db) if maintenance_db_id in self.connections: conn = self.connections[maintenance_db_id] # try to connect maintenance db if not connected if not conn.connected(): conn.connect() if conn.connected(): status, res = conn.execute_dict(u""" SELECT db.oid as did, db.datname, db.datallowconn, pg_encoding_to_char(db.encoding) AS serverencoding, has_database_privilege(db.oid, 'CREATE') as cancreate, datlastsysoid FROM pg_database db WHERE db.oid = {0}""".format(did)) if status and len(res['rows']) > 0: for row in res['rows']: self.db_info[did] = row database = self.db_info[did]['datname'] if did not in self.db_info: raise Exception( gettext( "Could not find the specified database.")) if not get_crypt_key()[0]: # the reason its not connected might be missing key raise CryptKeyMissing() if database is None: # Check SSH Tunnel is alive or not. if self.use_ssh_tunnel == 1: self.check_ssh_tunnel_alive() else: raise ConnectionLost(self.sid, None, None) my_id = (u'CONN:{0}'.format(conn_id)) if conn_id is not None else \ (u'DB:{0}'.format(database)) self.pinged = datetime.datetime.now() if my_id in self.connections: return self.connections[my_id] else: if async_ is None: async_ = 1 if conn_id is not None else 0 else: async_ = 1 if async_ is True else 0 self.connections[my_id] = Connection( self, my_id, database, auto_reconnect, async_, use_binary_placeholder=use_binary_placeholder, array_to_string=array_to_string) return self.connections[my_id]
def connection(self, **kwargs): database = kwargs.get('database', None) conn_id = kwargs.get('conn_id', None) auto_reconnect = kwargs.get('auto_reconnect', True) did = kwargs.get('did', None) async_ = kwargs.get('async_', None) use_binary_placeholder = kwargs.get('use_binary_placeholder', False) array_to_string = kwargs.get('array_to_string', False) if database is not None: if did is not None and did in self.db_info: self.db_info[did]['datname'] = database else: if did is None: database = self.db elif did in self.db_info: database = self.db_info[did]['datname'] else: maintenance_db_id = 'DB:{0}'.format(self.db) if maintenance_db_id in self.connections: conn = self.connections[maintenance_db_id] # try to connect maintenance db if not connected if not conn.connected(): conn.connect() if conn.connected(): status, res = conn.execute_dict(""" SELECT db.oid as did, db.datname, db.datallowconn, pg_catalog.pg_encoding_to_char(db.encoding) AS serverencoding, pg_catalog.has_database_privilege(db.oid, 'CREATE') as cancreate, datlastsysoid, datistemplate FROM pg_catalog.pg_database db WHERE db.oid = {0}""".format(did)) if status and len(res['rows']) > 0: for row in res['rows']: self.db_info[did] = row database = self.db_info[did]['datname'] if did not in self.db_info: raise ObjectGone( gettext( "Could not find the specified database.")) if not get_crypt_key()[0]: # the reason its not connected might be missing key raise CryptKeyMissing() if database is None: # Check SSH Tunnel is alive or not. if self.use_ssh_tunnel == 1: self.check_ssh_tunnel_alive() else: raise ConnectionLost(self.sid, None, None) my_id = ('CONN:{0}'.format(conn_id)) if conn_id is not None else \ ('DB:{0}'.format(database)) self.pinged = datetime.datetime.now() if my_id in self.connections: return self.connections[my_id] else: if async_ is None: async_ = 1 if conn_id is not None else 0 else: async_ = 1 if async_ is True else 0 self.connections[my_id] = Connection( self, my_id, database, auto_reconnect=auto_reconnect, async_=async_, use_binary_placeholder=use_binary_placeholder, array_to_string=array_to_string) return self.connections[my_id]