Skip to content

Commit

Permalink
Merge pull request #90 from pelonchasva/master
Browse files Browse the repository at this point in the history
Feature #28: List stored network (Windows, Linux and MacOS)
  • Loading branch information
sdushantha authored Dec 26, 2022
2 parents 2163db2 + 238eac8 commit c9d39c6
Show file tree
Hide file tree
Showing 4 changed files with 248 additions and 93 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ optional arguments:
--save-qr [PATH], -save [PATH]
Create the QR code and save it as an image
--ssid SSID, -s SSID Specify a SSID that you have previously connected to
--list, -l Lists all stored network SSID
--version Show version number
```

Expand Down
9 changes: 9 additions & 0 deletions wifi_password/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env python3

# Platfrom Names
LINUX = 'Linux'
MAC = 'MacOS'
WINDOWS = 'Windows'

# MacOS Airport package path
AIRPORT_PATH = "/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport"
203 changes: 203 additions & 0 deletions wifi_password/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
#!/usr/bin/env python3
import os
import sys
import re
import subprocess
import qrcode
import colorama

import constants

def get_platform() -> str:
"""
Returns the name of the platform where the application is currently running
"""
platforms = {
'linux': constants.LINUX,
'linux1': constants.LINUX,
'linux2': constants.LINUX,
'darwin': constants.MAC,
'win32': constants.WINDOWS
}

if not sys.platform in platforms:
return sys.platform

return platforms[sys.platform]

def get_profiles() -> list:
"""
Gets a list of names from saved wifi networks in the current platform
"""
profiles = []

platform = get_platform()

try:
if platform == constants.MAC:
# Command found here : https://coderwall.com/p/ghl-cg/list-known-wlans
profiles = run_command(f"defaults read ~/Library/Logs/com.apple.wifi.syncable-networks.plist | grep \" SSID\" | sed 's/^.*= \(.*\);$/\\1/' | sed 's/^\"\\(.*\)\"$/\\1/'").split('\n')
elif platform == constants.LINUX:
if os.getuid() != 0:
ssid = run_command(f"sudo ls /etc/NetworkManager/system-connections/ | grep .nmconnection").split('\n')
else:
ssid = run_command(f"ls /etc/NetworkManager/system-connections/ | grep .nmconnection").split('\n')

for entry in ssid:
profiles.append(entry.split('.nmconnection')[0])
elif platform == constants.WINDOWS:
# Reference: https://www.geeksforgeeks.org/getting-saved-wifi-passwords-using-python/
# getting meta data
meta_data = run_command('netsh wlan show profiles | findstr ":"')

if meta_data != "":
# splitting data line by line
data = meta_data.split('\n')

if len(data) > 0:
# skip the first element in data since it does not contain a valid profile returned by netsh command
profiles = [d.split(':')[1].strip(' .\r') for d in data[1:]]
except Exception as ex:
print(f'Error: {ex}')

return profiles

def generate_wifi_dict(profiles: list) -> dict:
"""
Generates a dictionary with the wifi name as key and the password as it's value
"""
wifi_dict = {}

if profiles is None:
print(f'List is not defined.')
return

if len(profiles) == 0:
print(f'List is empty.')
return

for ssid in profiles:
if get_platform() == constants.MAC and len(profiles) > 1:
password = "*****"
else:
password = get_password(ssid)

wifi_dict[ssid] = password

return wifi_dict

def get_password(ssid: str) -> str:
"""
Gets the password for a given SSID
"""
password = ""

if ssid == "" or ssid is None:
print("SSID is not defined")
return password

platform = get_platform()

try:
if platform == constants.MAC:
password = run_command(f"security find-generic-password -l \"{ssid}\" -D 'AirPort network password' -w")
elif platform == constants.LINUX:
# Check if the user is running with super user privilages
if os.getuid() != 0:
password = run_command(f"sudo nmcli -s -g 802-11-wireless-security.psk connection show '{ssid}'")
else:
password = run_command(f"nmcli -s -g 802-11-wireless-security.psk connection show '{ssid}'")
elif platform == constants.WINDOWS:
password = run_command(f"chcp 437 | netsh wlan show profile name=\"{ssid}\" key=clear | findstr Key")

if password != "":
password = re.findall(r"Key Content\s+:\s(.*)", password)

if len(password) > 0:
password = password[0]
else:
password = ""
except Exception as ex:
print(f'Error: {ex}')

return password

def run_command(command: str) -> str:
"""
Runs a given command using subprocess module
"""
if command == "" or command is None:
return ""

env = os.environ.copy()
env["LANG"] = "C"
output, _ = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, shell=True, env=env).communicate()
return output.decode("utf-8", errors="replace").rstrip("\r\n")

def print_dict(ssid: dict) -> None:
"""
Prints the contents of the given dictionary that contains the wifi name and password
"""
if ssid is None:
print(f'Dictionary is not defined.')
return

if len(ssid) == 0:
print(f'Dictionary is empty.')
return

print("----------------------------------------------")
print("{:<30}| {:<}".format("SSID", "Password"))
print("----------------------------------------------")

for key, value in ssid.items():
print("{:<30}| {:<}".format(key, value))

print("----------------------------------------------")
# If macOS and list

if get_platform() == constants.MAC and len(ssid) > 1:
print(f"Use 'wifi-password -s <SSID>' to find a specific WIFI password")

def generate_qr_code(ssid: str, password: str, path: str, show_qr: bool) -> None:
"""
Generates a QR code from a given ssid and password
Source: https://git.io/JtLIv
"""
if ssid == "" or ssid is None:
print('SSID is not specified, cannot generate QR code.')
return

text = f"WIFI:T:WPA;S:{ssid};P:{password};;"

try:
qr = qrcode.QRCode(version=1,
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=10,
border=4)
qr.add_data(text)

if show_qr:
print(f'---------- {ssid} ----------')
# This will emulate support for ANSI escape sequences, which is needed
# in order to display the QR code on Windows
colorama.init()
qr.make()
qr.print_tty()

if path:
file_name = ssid.replace(" ", "_") + ".png"

if path == "STORE_LOCALLY":
path = file_name

try:
img = qr.make_image()
img.save(path)

print(f"QR code has been saved to {path}")
except FileNotFoundError:
print(f"No such file/directory: '{path}'")
except Exception as ex:
print(f'QR Code Error: {ex}')
Loading

0 comments on commit c9d39c6

Please sign in to comment.