GCC Code Coverage Report


Directory: ./
File: panels/system/users/pw-utils.c
Date: 2024-05-04 07:58:27
Exec Total Coverage
Lines: 0 89 0.0%
Functions: 0 5 0.0%
Branches: 0 48 0.0%

Line Branch Exec Source
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 *
3 * Copyright 2012 Red Hat, Inc,
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, see <http://www.gnu.org/licenses/>.
17 *
18 * Written by: Matthias Clasen <mclasen@redhat.com>
19 */
20
21 #include "config.h"
22
23 #include "pw-utils.h"
24
25 #include <glib.h>
26 #include <glib/gi18n.h>
27
28 #include <pwquality.h>
29
30 static pwquality_settings_t *
31 get_pwq (void)
32 {
33 static pwquality_settings_t *settings;
34
35 if (settings == NULL) {
36 gchar *err = NULL;
37 gint rv = 0;
38
39 settings = pwquality_default_settings ();
40 pwquality_set_int_value (settings, PWQ_SETTING_MAX_SEQUENCE, 4);
41
42 rv = pwquality_read_config (settings, NULL, (gpointer)&err);
43 if (rv < 0) {
44 g_warning ("failed to read pwquality configuration: %s\n",
45 pwquality_strerror (NULL, 0, rv, err));
46 pwquality_free_settings (settings);
47
48 /* Load just default settings in case of failure. */
49 settings = pwquality_default_settings ();
50 pwquality_set_int_value (settings, PWQ_SETTING_MAX_SEQUENCE, 4);
51 }
52 }
53
54 return settings;
55 }
56
57 gint
58 pw_min_length (void)
59 {
60 gint value = 0;
61 gint rv;
62
63 rv = pwquality_get_int_value (get_pwq (), PWQ_SETTING_MIN_LENGTH, &value);
64 if (rv < 0) {
65 g_warning ("Failed to read pwquality setting: %s\n",
66 pwquality_strerror (NULL, 0, rv, NULL));
67 }
68
69 return value;
70 }
71
72 gchar *
73 pw_generate (void)
74 {
75 gchar *res;
76 gint rv;
77
78 rv = pwquality_generate (get_pwq (), 0, &res);
79
80 if (rv < 0) {
81 g_warning ("Password generation failed: %s\n",
82 pwquality_strerror (NULL, 0, rv, NULL));
83 return NULL;
84 }
85
86 return res;
87 }
88
89 static const gchar *
90 pw_error_hint (gint error)
91 {
92 switch (error) {
93 case PWQ_ERROR_SAME_PASSWORD:
94 return C_("Password hint", "The new password needs to be different from the old one.");
95 case PWQ_ERROR_CASE_CHANGES_ONLY:
96 return C_("Password hint", "Try changing some letters and numbers.");
97 case PWQ_ERROR_TOO_SIMILAR:
98 return C_("Password hint", "Try changing the password a bit more.");
99 case PWQ_ERROR_USER_CHECK:
100 return C_("Password hint", "A password without your user name would be stronger.");
101 case PWQ_ERROR_GECOS_CHECK:
102 return C_("Password hint", "Try to avoid using your name in the password.");
103 case PWQ_ERROR_BAD_WORDS:
104 return C_("Password hint", "Try to avoid some of the words included in the password.");
105 case PWQ_ERROR_ROTATED:
106 return C_("Password hint", "Try changing the password a bit more.");
107 case PWQ_ERROR_CRACKLIB_CHECK:
108 return C_("Password hint", "Try to avoid common words.");
109 case PWQ_ERROR_PALINDROME:
110 return C_("Password hint", "Try to avoid reordering existing words.");
111 case PWQ_ERROR_MIN_DIGITS:
112 return C_("Password hint", "Try to use more numbers.");
113 case PWQ_ERROR_MIN_UPPERS:
114 return C_("Password hint", "Try to use more uppercase letters.");
115 case PWQ_ERROR_MIN_LOWERS:
116 return C_("Password hint", "Try to use more lowercase letters.");
117 case PWQ_ERROR_MIN_OTHERS:
118 return C_("Password hint", "Try to use more special characters, like punctuation.");
119 case PWQ_ERROR_MIN_CLASSES:
120 return C_("Password hint", "Try to use a mixture of letters, numbers and punctuation.");
121 case PWQ_ERROR_MAX_CONSECUTIVE:
122 return C_("Password hint", "Try to avoid repeating the same character.");
123 case PWQ_ERROR_MAX_CLASS_REPEAT:
124 return C_("Password hint", "Try to avoid repeating the same type of character: you need to mix up letters, numbers and punctuation.");
125 case PWQ_ERROR_MAX_SEQUENCE:
126 return C_("Password hint", "Try to avoid sequences like 1234 or abcd.");
127 case PWQ_ERROR_MIN_LENGTH:
128 return C_("Password hint", "Password needs to be longer. Try to add more letters, numbers and punctuation.");
129 case PWQ_ERROR_EMPTY_PASSWORD:
130 return C_("Password hint", "Mix uppercase and lowercase and try to use a number or two.");
131 default:
132 return C_("Password hint", "Adding more letters, numbers and punctuation will make the password stronger.");
133 }
134 }
135
136 gdouble
137 pw_strength (const gchar *password,
138 const gchar *old_password,
139 const gchar *username,
140 const gchar **hint,
141 gint *strength_level)
142 {
143 gint rv, level, length = 0;
144 gdouble strength = 0.0;
145 void *auxerror;
146
147 rv = pwquality_check (get_pwq (),
148 password, old_password, username,
149 &auxerror);
150
151 if (password != NULL)
152 length = strlen (password);
153
154 strength = CLAMP (0.01 * rv, 0.0, 1.0);
155 if (rv < 0) {
156 level = (length > 0) ? 1 : 0;
157 }
158 else if (strength < 0.50) {
159 level = 2;
160 } else if (strength < 0.75) {
161 level = 3;
162 } else if (strength < 0.90) {
163 level = 4;
164 } else {
165 level = 5;
166 }
167
168 if (length && length < pw_min_length())
169 *hint = pw_error_hint (PWQ_ERROR_MIN_LENGTH);
170 else
171 *hint = pw_error_hint (rv);
172
173 if (strength_level)
174 *strength_level = level;
175
176 return strength;
177 }
178