Commit 77095543 authored by Bilal Elmoussaoui's avatar Bilal Elmoussaoui

start working on 2.0

parent 7a17189a
[*]
indent_style = space
trim_trailing_whitespace = true
insert_final_newline = true
charset = utf-8
end_of_line = cr
root = true
[*.py]
indent_size = 4
[*.build]
indent_size = 2
......@@ -64,46 +64,10 @@ target/
#Ipython Notebook
.ipynb_checkpoints
# Unneeded files
NEWS
README
AUTHORS
ChangeLog
COPYING
INSTALL
aclocal.m4
py-compile
install-sh
gnome-twofactorauth
stamp-h1
config.h
missing
ltmain.sh
configure
config.status
config.log
config.h.in
Makefile
Makefile.in
TwoFactorAuth/Makefile
TwoFactorAuth/Makefile.in
TwoFactorAuth/widgets/Makefile
TwoFactorAuth/widgets/Makefile.in
TwoFactorAuth/models/Makefile
TwoFactorAuth/models/Makefile.in
data/Makefile
data/Makefile.in
data/applications/Makefile
data/applications/Makefile.in
schemas/Makefile.in
schemas/Makefile
schemas/*.valid
po/stamp-it
po/*.gmo
po/POTFILES
po/Makefile.in.in
*.valid
*.compiled
*.desktop
*.gresource
*.ui~
.vscode/
......@@ -18,3 +18,5 @@
You should have received a copy of the GNU General Public License
along with Gnome-TwoFactorAuth. If not, see <http://www.gnu.org/licenses/>.
"""
from .application import Application
from .utils import is_gnome
......@@ -17,10 +17,11 @@
You should have received a copy of the GNU General Public License
along with Gnome-TwoFactorAuth. If not, see <http://www.gnu.org/licenses/>.
"""
from hashlib import sha256
import sqlite3
import logging
from gi.repository import GnomeKeyring as GK, GLib
from hashlib import sha256
from Authenticator.utils import create_file
......
from abc import ABCMeta, abstractmethod
class Observer(object):
__metaclass__ = ABCMeta
@abstractmethod
def update(self, *args, **kwargs):
pass
......@@ -17,11 +17,13 @@
You should have received a copy of the GNU General Public License
along with Gnome-TwoFactorAuth. If not, see <http://www.gnu.org/licenses/>.
"""
from PIL import Image
from zbarlight import scan_codes
from urllib.parse import urlparse, parse_qsl
import logging
from os import remove, path
from urllib.parse import urlparse, parse_qsl
from PIL import Image
from zbarlight import scan_codes
from Authenticator.models.code import Code
......@@ -29,17 +31,18 @@ class QRReader:
def __init__(self, filename):
self.filename = filename
self._codes = None
def read(self):
with open(self.filename, 'rb') as image_file:
image = Image.open(image_file)
image.load()
self.codes = scan_codes('qrcode', image)
self._codes = scan_codes('qrcode', image)
self.remove()
if self.codes:
otpauth_url = self.codes[0].decode()
self.codes = dict(parse_qsl(urlparse(otpauth_url)[4]))
return self.codes
if self._codes:
otpauth_url = self._codes[0].decode()
self._codes = dict(parse_qsl(urlparse(otpauth_url)[4]))
return self._codes
else:
logging.error("Invalid QR image")
return None
......@@ -56,9 +59,9 @@ class QRReader:
"""
Validate if the QR code is a valid tfa
"""
if isinstance(self.codes, dict):
if set(["issuer", "secret"]).issubset(self.codes.keys()):
return Code.is_valid(self.codes["secret"])
if isinstance(self._codes, dict):
if set(["issuer", "secret"]).issubset(self._codes.keys()):
return Code.is_valid(self._codes["secret"])
else:
return False
else:
......
......@@ -23,6 +23,9 @@ from hashlib import sha256
class Settings(Gio.Settings):
"""Settings handler."""
# Default Settings instance
instance = None
def __init__(self):
Gio.Settings.__init__(self)
......@@ -32,65 +35,104 @@ class Settings(Gio.Settings):
gsettings.__class__ = Settings
return gsettings
def get_window_size(self):
@staticmethod
def get_default():
"""Return the default instance of Settings."""
if Settings.instance is None:
Settings.instance = Settings.new()
return Settings.instance
@property
def window_size(self):
"""Return the window size."""
return tuple(self.get_value('window-size'))
def set_window_size(self, size):
@window_size.setter
def window_size(self, size):
"""Set the window size."""
size = GLib.Variant('ai', list(size))
self.set_value('window-size', size)
def get_default_size(self):
@property
def default_size(self):
"""Return the default window size."""
return tuple(self.get_default_value('window-size'))
def get_window_position(self):
@property
def window_position(self):
"""Return the window's position."""
return tuple(self.get_value('window-position'))
def set_window_postion(self, position):
@window_position.setter
def window_postion(self, position):
"""Set the window postion."""
position = GLib.Variant('ai', list(position))
self.set_value('window-position', position)
def set_is_night_mode(self, statue):
self.set_boolean('night-mode', statue)
@is_night_mode.setter
def is_night_mode(self, status):
"""Set the night mode."""
self.set_boolean('night-mode', status)
def get_is_night_mode(self):
@property
def is_night_mode(self):
"""Is night mode?"""
return self.get_boolean('night-mode')
def set_can_be_locked(self, status):
@can_be_locked.setter
def can_be_locked(self, status):
"""set the app to be locked."""
self.set_boolean('state', status)
def get_can_be_locked(self):
@property
def can_be_locked(self):
"""Return if the app can be locked or not."""
return self.get_boolean('state')
def set_is_locked(self, statue):
self.set_boolean('locked', statue)
@is_locked.status
def is_locked(self, status):
"""Set the app to be locked."""
self.set_boolean('locked', status)
def get_is_locked(self):
@property
def is_locked(self):
"""Return if the app is locked."""
return self.get_boolean('locked')
def set_password(self, password):
@password.setter
def password(self, password):
"""Set a new password."""
password = sha256(password.encode('utf-8')).hexdigest()
self.set_string("password", password)
def compare_password(self, password):
"""Compare a password with the current one."""
password = sha256(password.encode('utf-8')).hexdigest()
return password == self.get_password()
def is_password_set(self):
return len(self.get_password()) != 0
return password == self.password
def get_password(self):
@property
def password(self):
"""Return the password."""
return self.get_string("password")
def get_auto_lock_status(self):
@property
def auto_lock(self):
"""Return the Auto lock status."""
return self.get_boolean("auto-lock")
def set_auto_lock_status(self, status):
@auto_lock.setter
def auto_lock(self, status):
"""Set the auto lock status."""
self.set_boolean("auto-lock", status)
def get_auto_lock_time(self):
@property
def auto_lock_time(self):
"""Get auto lock time."""
return self.get_int("auto-lock-time")
def set_auto_lock_time(self, auto_lock_time):
@auto_lock_time.setter
def auto_lock_time(self, auto_lock_time):
"""Set the auto lock time."""
if auto_lock_time < 1 or auto_lock_time > 15:
auto_lock_time = 3
self.set_int("auto-lock-time", auto_lock_time)
FROM ubuntu:16.04
RUN apt-get -y update
# Install dependecies
RUN apt-get install -y python3 libzbar-dev gnome-screenshot gnome-keyring git python-gobject
RUN pip install pyotp pyaml Pillow zbarlight setuptools
RUN pip install ninja meson
# Build Gnome-TwoFactorAuth usinn Meson
RUN git clone https://github.com/bil-elmoussaoui/Gnome-Authenticator && cd ./Gnome-Authenticator
RUN mkdir build && cd ./build
RUN meson .. && ninja && sudo ninja install
CMD gnome-authenticator
......@@ -12,33 +12,38 @@ version](https://img.shields.io/badge/python-3.3%2B-blue.svg)
- `meson 0.38+`
- `ninja`
- `pyotp`
- `pyaml`
- `Pillow`
- `zbarlight` depends on `zbar`
- `libzbar-dev` on Ubuntu
- `zbar` on Arch
- `libzbar-dev` on Ubuntu
- `zbar` on Arch
- `gnome-keyring`
- `gnome-screenshot`
<sub>PS: The application was only tested on Arch with Gtk 3.20+, but it should work nicely with older versions too. Keyboard shortcuts widget won't be shown for older versions.</sub>
<sub>
PS: The application was only tested on Arch with Gtk 3.20+, but it should work nicely with older versions too. Keyboard shortcuts widget won't be shown for older versions.
</sub>
### Screenshots
<img src="screenshots/screenshot7.png" width="280" /> <img src="screenshots/screenshot1.png" width="280" /> <img src="screenshots/screenshot2.png" width="280" />
### Features
- QR code scanner
- Beautiful UI
- Handy shortcuts
- Huge database of (290+) websites/applications
### Installation
- On Arch :
```bash
yaourt -S gnome-twofactorauth
```
- On Ubuntu (xenial/yakkety) using GetDeb Apps PPA:
```bash
wget -q -O - http://archive.getdeb.net/getdeb-archive.key | sudo apt-key add -
sudo sh -c 'echo "deb http://archive.getdeb.net/ubuntu xenial-getdeb apps" >> /etc/apt/sources.list.d/getdeb.list'
......@@ -47,36 +52,47 @@ sudo apt install gnome-twofactorauth
```
### Credits
- Websites and application icons are from Paper theme, created by [Sam Hewitt](https://github.com/snwh)
- Applications/Websites database are from [twofactorauth](https://github.com/2factorauth/twofactorauth), by 2factorauth team
### How to build from source
1 - Clone the repository
```bash
git clone https://github.com/bil-elmoussaoui/Gnome-Authenticator && cd ./Gnome-Authenticator
```
2 - Install Python dependecies
```bash
sudo pip install pyotp zbarlight pyaml Pillow meson ninja
```
<sub>PS : In some distributions you will need to use `pip3` instead of `pip` to install the compatible version of the package with Python 3.</sub> <br>
3 - Afterwards
```bash
mkdir build && cd build
meson ..
ninja
sudo ninja install
meson builddir
sudo ninja -C builddir install
```
4 - You can run the application from the desktop file or from terminal using
```bash
gnome-authenticator
```
<sub>Arch users can build from source directly using AUR `yaourt -S gnome-twofactorauth-git`</sub>
### Flags
- `--debug` <br/>
Open the application with debug flags
- `--version`<br/>
Shows the version number of the application
- `--about`<br/>
Shows the about dialog
- `--debug`
Open the application with debug flags
- `--version`
Shows the version number of the application
- `--about`
Shows the about dialog
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.19.0 -->
<interface>
<requires lib="gtk+" version="3.16"/>
<object class="GtkAboutDialog" id="AboutDialog">
<property name="can_focus">False</property>
<property name="type">popup</property>
<property name="resizable">False</property>
<property name="window_position">center</property>
<property name="destroy_with_parent">True</property>
<property name="type_hint">menu</property>
<property name="program_name">Gnome Authenticator</property>
<property name="version">0.1.1</property>
<property name="comments" translatable="yes">Simple application to generate 2 factor authentication code</property>
<property name="license" translatable="yes">This program comes with absolutely no warranty. See the &lt;a href="http://www.gnu.org/licenses/gpl-3.0.html"&gt;GNU General Public License, version 3 or later&lt;/a&gt; for details.</property>
<property name="authors">Bilal Elmoussaoui</property>
<property name="logo_icon_name">org.gnome.Authenticator</property>
<property name="license_type">gpl-3-0</property>
<property name="website">https://github.com/bil-elmoussaoui/Gnome-Authenticator</property>
<property name="website_label" translatable="yes">Github</property>
<property name="artists">Alexandros Felekidis</property>
<child internal-child="vbox">
<object class="GtkBox" id="aboutdialog-vbox">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox" id="aboutdialog-action_area">
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
</interface>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkBox" id="MainBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="valign">start</property>
<property name="row_spacing">6</property>
<property name="column_spacing">6</property>
<child>
<object class="GtkImage" id="ApplicationLogo">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="stock">gtk-missing-image</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="ApplicationName">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<style>
<class name="application-name"/>
</style>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<style>
<class name="application-list-row"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
</interface>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkListBox" id="ApplicationsList">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<style>
<class name="applications-list"/>
</style>
</object>
<object class="GtkImage" id="image1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">search-symbolic</property>
</object>
<object class="GtkWindow" id="ApplicationsWindow">
<property name="width_request">500</property>
<property name="height_request">650</property>
<property name="can_focus">False</property>
<property name="resizable">False</property>
<property name="modal">True</property>
<property name="window_position">center-on-parent</property>
<property name="default_width">500</property>
<property name="default_height">650</property>
<property name="destroy_with_parent">True</property>
<signal name="destroy" handler="on_close" swapped="no"/>
<signal name="key-press-event" handler="on_key_press" swapped="no"/>
<child>
<object class="GtkStack" id="ApplicationsStack">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="transition_duration">400</property>
<property name="transition_type">crossfade</property>
<child>
<object class="GtkBox" id="MainBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<placeholder/>
</child>
<child>
<object class="GtkScrolledWindow" id="ApplicationListScrolled">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">etched-in</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="name">applicationsliststack</property>
<property name="title" translatable="yes">page0</property>
</packing>
</child>
<child>
<object class="GtkGrid" id="LoadingGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="border_width">18</property>
<child>
<object class="GtkLabel" id="LoadingLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Loading data..</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkSpinner" id="LoadingSpinner">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
<packing>
<property name="name">loadingstack</property>
<property name="title" translatable="yes">page1</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<child type="titlebar">
<object class="GtkHeaderBar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="title">Select an application</property>
<child>
<object class="GtkButton" id="CancelButton">
<property name="label" translatable="yes">Cancel</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_close" swapped="no"/>
<style>
<class name="destructive-action"/>
</style>
</object>
</child>
<child>
<object class="GtkButton" id="NextButton">
<property name="label" translatable="yes">Next</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_apply" swapped="no"/>
<style>
<class name="suggested-action"/>
</style>
</object>
<packing>
<property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkToggleButton" id="SearchButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Search</property>
<property name="image">image1</property>
</object>
<packing>
<property name="pack_type">end</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
websites:
- name: AeroFS
url: https://www.aerofs.com/
tfa: Yes
software: Yes
img: aerofs.png
doc: https://www.aerofs.com/blog/two-factor-authentication-for-hybrid-and-private-cloud-md/
- name: Apple iCloud
url: https://www.icloud.com
img: icloud.png
tfa: Yes
sms: Yes
software: Yes
exceptions:
text: "See https://support.apple.com/HT202656 for a list of supported SMS carriers."
doc: https://support.apple.com/HT204152
- name: Backblaze
url: https://www.backblaze.com
img: backblaze.png
tfa: Yes
sms: Yes
doc: https://www.backblaze.com/blog/two-factor-verification-for-backblaze/
- name: Bitcasa
url: https://www.bitcasa.com/
twitter: Bitcasa
img: bitcasa.png
tfa: No
- name: Box
url: https://app.box.com/
img: box.png
tfa: Yes
sms: Yes
doc: https://support.box.com/hc/en-us/articles/200526658-Can-I-enable-2-step-verification-for-my-account-
- name: CloudApp
url: https://www.getcloudapp.com/
twitter: cloudapp
img: cloudapp.png
tfa: No
facebook: getcloudapp
- name: CrashPlan
url: https://www.crashplan.com
twitter: crashplan
img: crashplan.png
tfa: No
facebook: CrashPlan
- name: Dropbox
url: https://www.dropbox.com
img: dropbox.png
tfa: Yes
sms: Yes
software: Yes
hardware: Yes
doc: https://www.dropbox.com/help/363/en
- name: Evernote
url: https://evernote.com