You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
qubes-installer-qubes-os/firstboot/firstboot/pwcheck.py

227 lines
7.1 KiB

#
# pwcheck.py
#
# Copyright (C) 2010 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Red Hat Author(s): Martin Gracik <mgracik@redhat.com>
#
import re
import pwquality
import pygtk
pygtk.require("2.0")
import gtk
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("pwcheck")
import gettext
_ = lambda x: gettext.ldgettext("firstboot", x)
def clamp(value, lowerbound, upperbound):
return min(max(value, lowerbound), upperbound)
class Password(object):
MIN_STRENGTH = 0
MAX_STRENGTH = 100
STRENGTH_STRINGS = [ _("Very weak"),
_("Weak"),
_("Fairly strong"),
_("Strong"),
_("Very strong") ]
def __init__(self, password, username=None):
self.password = password
self.username = username
self.pwq_settings = pwquality.PWQSettings()
self.pwq_settings.read_config()
self.strength = self.MIN_STRENGTH
self.pwq_msg = ''
try:
self.strength = self.pwq_settings.check(self.password, None, self.username)
except pwquality.PWQError as (e, msg):
self.pwq_msg = msg
self.strength = clamp(self.strength, self.MIN_STRENGTH, self.MAX_STRENGTH)
@property
def strength_frac(self):
return float(self.strength) / self.MAX_STRENGTH
@property
def strength_string(self):
strings_count = len(self.STRENGTH_STRINGS)
index = int(self.strength / (self.MAX_STRENGTH / strings_count))
try:
return self.STRENGTH_STRINGS[index]
except IndexError:
return self.STRENGTH_STRINGS[-1]
def __str__(self):
return "%s" % self.password
class StrengthMeter(gtk.DrawingArea):
COLORS = [(213.0/255.0, 4.0/255.0, 4.0/255.0),
(234.0/255.0, 236.0/255.0, 31.0/255.0),
(141.0/255.0, 133.0/255.0, 241.0/255.0),
(99.0/255.0, 251.0/255.0, 107.0/255.0)]
def __init__(self):
super(StrengthMeter, self).__init__()
self.connect("expose_event", self.expose)
self._fraction = 0.0
def curved_rectangle(self, context, x0, y0, width, height, radius):
if not width or not height:
return
x1 = x0 + width
y1 = y0 + height
if width / 2 < radius:
if height / 2 < radius:
context.move_to (x0, (y0 + y1) / 2)
context.curve_to(x0 ,y0, x0, y0, (x0 + x1) / 2, y0)
context.curve_to(x1, y0, x1, y0, x1, (y0 + y1) / 2)
context.curve_to(x1, y1, x1, y1, (x1 + x0) / 2, y1)
context.curve_to(x0, y1, x0, y1, x0, (y0 + y1) / 2)
else:
context.move_to (x0, y0 + radius)
context.curve_to(x0, y0, x0, y0, (x0 + x1) / 2, y0)
context.curve_to(x1, y0, x1, y0, x1, y0 + radius)
context.line_to (x1, y1 - radius)
context.curve_to(x1, y1, x1, y1, (x1 + x0) / 2, y1)
context.curve_to(x0, y1, x0, y1, x0, y1 - radius)
else:
if height / 2 < radius:
context.move_to (x0, (y0 + y1) / 2)
context.curve_to(x0, y0, x0 , y0, x0 + radius, y0)
context.line_to (x1 - radius, y0)
context.curve_to(x1, y0, x1, y0, x1, (y0 + y1) / 2)
context.curve_to(x1, y1, x1, y1, x1 - radius, y1)
context.line_to (x0 + radius, y1)
context.curve_to(x0, y1, x0, y1, x0, (y0 + y1) / 2)
else:
context.move_to (x0, y0 + radius)
context.curve_to(x0 , y0, x0 , y0, x0 + radius, y0)
context.line_to (x1 - radius, y0)
context.curve_to(x1, y0, x1, y0, x1, y0 + radius)
context.line_to (x1, y1 - radius)
context.curve_to(x1, y1, x1, y1, x1 - radius, y1)
context.line_to (x0 + radius, y1)
context.curve_to(x0, y1, x0, y1, x0, y1 - radius)
context.close_path()
def expose(self, widget, event):
# Create the cairo context
context = widget.window.cairo_create()
# Restrict cairo to the exposed area
context.rectangle(event.area.x, event.area.y,
event.area.width, event.area.height)
context.clip()
# Draw the widget
self.draw(context)
return False
def draw(self, context):
alloc = self.get_allocation()
context.translate(-alloc.x, -alloc.y)
context.save()
context.set_source_rgb(0.0, 0.0, 0.0)
context.set_line_width(1)
self.curved_rectangle(context, alloc.x + 0.5, alloc.y + 0.5,
alloc.width - 1, alloc.height - 1,
4)
context.stroke()
context.restore()
context.save()
r, g, b = self.get_color()
context.set_source_rgb(r, g, b)
context.rectangle(alloc.x + 1, alloc.y + 1,
self.fraction * (alloc.width - 2), alloc.height - 2)
context.fill_preserve()
context.restore()
def redraw(self):
if self.window:
alloc = self.get_allocation()
rect = gtk.gdk.Rectangle(0, 0, alloc.width, alloc.height)
self.window.invalidate_rect(rect, True)
self.queue_draw_area(alloc.x, alloc.y, alloc.width, alloc.height)
self.window.process_updates(True)
@property
def fraction(self):
return self._fraction
@fraction.setter
def fraction(self, fraction):
self._fraction = fraction
self.redraw()
def get_color(self):
if self.fraction < 0.5:
return self.COLORS[0]
elif self.fraction < 0.75:
return self.COLORS[1]
elif self.fraction < 0.90:
return self.COLORS[2]
else:
return self.COLORS[3]
class StrengthMeterWithLabel(gtk.HBox):
def __init__(self):
super(StrengthMeterWithLabel, self).__init__()
self.meter = StrengthMeter()
self.meter.set_size_request(120, 8)
self.alignment = gtk.Alignment(0.0, 0.5)
self.alignment.add(self.meter)
self.label = gtk.Label()
self.label.set_alignment(0.0, 0.5)
self.pack_start(self.alignment, expand=False)
self.pack_start(self.label)
self.set_spacing(10)
def set_fraction(self, fraction):
self.meter.fraction = fraction
def set_text(self, text):
self.label.set_text(text)