Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion PLATFORMS.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
- Calix B6
- Casa Systems CMTS
- Centec Networks
- Check Point GAiA
- Cisco AireOS (Wireless LAN Controllers)
- Cisco ASA
- Cisco S200
Expand Down Expand Up @@ -92,7 +93,6 @@
- Cisco APIC (Linux)
- Cisco Telepresence
- Cisco Viptela
- Check Point GAiA
- Corelight Linux
- Coriant
- Cumulus VX Linux
Expand Down
30 changes: 26 additions & 4 deletions netmiko/base_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -2011,6 +2011,29 @@ def check_enable_mode(self, check_string: str = "") -> bool:
output = self.read_until_prompt(read_entire_line=True)
return check_string in output

def enable_secret_handler(
self,
pattern: str,
output: str,
re_flags: int = re.IGNORECASE,
) -> str:
"""
Some platforms require special handling when entering 'enable' mode.

Send the "secret" in response to password pattern

:param pattern: pattern to search for indicating device is waiting for password

:param output: Accumulated output from 'enable()' method.

:param re_flags: Regular expression flags used in conjunction with pattern

"""
if re.search(pattern, output, flags=re_flags):
self.write_channel(self.normalize_cmd(self.secret))
new_output = self.read_until_prompt()
return new_output

def enable(
self,
cmd: str = "",
Expand Down Expand Up @@ -2054,10 +2077,9 @@ def enable(
pattern=pattern, re_flags=re_flags, read_entire_line=True
)

# Send the "secret" in response to password pattern
if re.search(pattern, output, flags=re_flags):
self.write_channel(self.normalize_cmd(self.secret))
output += self.read_until_prompt()
output += self.enable_secret_handler(
pattern=pattern, output=output, re_flags=re_flags
)

# Search for terminating pattern if defined
if enable_pattern and not re.search(enable_pattern, output):
Expand Down
77 changes: 61 additions & 16 deletions netmiko/checkpoint/checkpoint_gaia_ssh.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import time
import re
from typing import Optional, Any

from netmiko.no_config import NoConfig
from netmiko.base_connection import BaseConnection
Expand All @@ -13,6 +14,13 @@ class CheckPointGaiaSSH(NoConfig, BaseConnection):

prompt_pattern = r"[>#]"

def __init__(self, *args: Any, **kwargs: Any) -> None:
# Kept running into issues with command_echo and duplicate echoes of commands.
self.fast_cli = False
fast_cli = kwargs.get("fast_cli") or False
kwargs["fast_cli"] = fast_cli
return super().__init__(*args, **kwargs)

def session_preparation(self) -> None:
"""
Prepare the session after the connection has been established.
Expand All @@ -27,26 +35,63 @@ def session_preparation(self) -> None:
time.sleep(0.3 * self.global_delay_factor)
self.clear_buffer()

def command_echo_read(self, cmd: str, read_timeout: float) -> str:
"""Check Point clish double echoes the command (at least sometimes)"""
def check_enable_mode(self, check_string: str = "#") -> bool:
"""Check if in enable mode. Return boolean."""
return super().check_enable_mode(check_string=check_string)

re_cmd = re.escape(cmd)
pattern = rf"{self.prompt_pattern}\s{re_cmd}"
def enable_secret_handler(
self,
pattern: str,
output: str,
re_flags: int = re.IGNORECASE,
) -> str:
"""
Check Point Gaia requires very particular timing for this 'expert'
password handling to work.

# Make sure you read until you detect the command echo (avoid getting out of sync)
new_data = self.read_until_pattern(pattern=pattern, read_timeout=read_timeout)
Send the "secret" in response to password pattern
"""
if re.search(pattern, output, flags=re_flags):
self.write_channel(self.secret)
time.sleep(0.3 * self.global_delay_factor)
self.write_channel(self.RETURN)
time.sleep(0.3 * self.global_delay_factor)
new_output = self.read_until_pattern(pattern=self.prompt_pattern)
return new_output

# There can be echoed prompts that haven't been cleared before the cmd echo
# this can later mess up the trailing prompt pattern detection. Clear this out.
lines = new_data.split(cmd)
if len(lines) in [2, 3]:
# lines[-1] should realistically just be the null string
new_data = f"{cmd}{lines[-1]}"
else:
# cmd exists in the output multiple times? Just retain the original output
pass
def enable(
self,
cmd: str = "expert",
pattern: str = r"expert password",
enable_pattern: Optional[str] = r"\#",
check_state: bool = True,
re_flags: int = re.IGNORECASE,
) -> str:
"""
Enter expert mode.

Check Point Gaia is very finicky on the timing of sending this 'expert' password.
"""
output = super().enable(
cmd=cmd,
pattern=pattern,
enable_pattern=enable_pattern,
check_state=check_state,
re_flags=re_flags,
)
self.set_base_prompt()
return output

return new_data
def exit_enable_mode(self, exit_command: str = "exit") -> str:
"""Exit expert mode."""
output = ""
if self.check_enable_mode():
self.write_channel(self.normalize_cmd(exit_command))
output += self.read_until_pattern(pattern=r">")
self.set_base_prompt()
if self.check_enable_mode():
raise ValueError("Failed to exit enable mode.")
return output

def save_config(
self, cmd: str = "", confirm: bool = False, confirm_response: str = ""
Expand Down
8 changes: 8 additions & 0 deletions tests/test_netmiko_show.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,14 @@ def test_enable_mode(net_connect, commands, expected_responses):
except AttributeError:
assert True

# Now verify you can exit enable mode
try:
net_connect.exit_enable_mode()
prompt = net_connect.find_prompt()
assert prompt == expected_responses["router_prompt"]
except AttributeError:
assert True


def test_disconnect(net_connect, commands, expected_responses):
"""Terminate the SSH session."""
Expand Down
Loading