Merge ubiquity:focal_ecryption_recovery_key into ubiquity:focal

Proposed by Jean-Baptiste Lallement
Status: Merged
Merged at revision: 42c32fe6ad6e98d3c07ecbe815f28c03ecea9500
Proposed branch: ubiquity:focal_ecryption_recovery_key
Merge into: ubiquity:focal
Diff against target: 1289 lines (+772/-83)
8 files modified
debian/ubiquity.templates (+90/-1)
gui/gtk/stepPartCrypto.ui (+427/-77)
scripts/plugininstall.py (+51/-0)
tests/test_gtkui.py (+3/-1)
ubiquity/components/plugininstall.py (+2/-0)
ubiquity/misc.py (+37/-0)
ubiquity/plugins/ubi-partman.py (+156/-4)
ubiquity/validation.py (+6/-0)
Reviewer Review Type Date Requested Status
Didier Roche-Tolomelli (community) Approve
Review via email: mp+405767@code.launchpad.net

Commit message

This is a backport of the recovery key feature introduced in 21.04 and improved for 21.10

To post a comment you must log in.
Revision history for this message
Didier Roche-Tolomelli (didrocks) wrote :

LGTM with the additional set_visible(False).

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/debian/ubiquity.templates b/debian/ubiquity.templates
2index 5528e77..d3b8268 100644
3--- a/debian/ubiquity.templates
4+++ b/debian/ubiquity.templates
5@@ -782,6 +782,15 @@ _Description: Error configuring connection to Active Directory
6 <a href="https://discourse.ubuntu.com/t/service-sssd/11579">ubuntu.com/activedirectory</a>
7 for help.
8
9+Template: ubiquity/install/broken_luks_add_key
10+Type: error
11+_Description: Error setting LUKS recovery key
12+ An error occurred while setting the recovery key. The
13+ installation will continue, but you may have to manually add the recovery
14+ key in the installed system with the command:
15+ .
16+ cryptsetup luksAddKey <device>
17+
18 Template: ubiquity/install/md5_check
19 Type: boolean
20 Default: true
21@@ -1716,4 +1725,84 @@ _Description: That name already exists on the network.
22
23 Template: ubiquity/text/domain_connection_error
24 Type: text
25-_Description: Failed to connect to domain.
26\ No newline at end of file
27+_Description: Failed to connect to domain.
28+
29+Template: ubiquity/text/recovery_key_enable
30+Type: text
31+_Description:
32+ Enable recovery key:
33+
34+Template: ubiquity/text/recovery_key_label
35+Type: text
36+_Description:
37+ Recovery key:
38+
39+Template: ubiquity/text/verified_recovery_key_label
40+Type: text
41+_Description:
42+ Confirm recovery key:
43+
44+Template: ubiquity/text/show_recovery_key
45+Type: text
46+_Description:
47+ Display recovery key:
48+
49+Template: ubiquity/text/recovery_key_warning
50+Type: text
51+_Description:
52+ A recovery key is generated and will be temporarily saved on the live system.
53+ You can select an alternate location. Save this file and keep it in a safe
54+ place elsewhere before rebooting.
55+
56+Template: ubiquity/text/recovery_key_location_label
57+Type: text
58+_Description: Location:
59+
60+Template: ubiquity/text/recovery_key_location_warning
61+Type: text
62+_Description:
63+ It is not recommended to store the key on a non removable device.
64+
65+Template: ubiquity/crypto_key
66+Type: password
67+_Description: Crypto key for LUKS + LVM
68+
69+Template: ubiquity/recovery_key
70+Type: password
71+_Description: Recovery key for LUKS + LVM
72+
73+Template: ubiquity/text/save_recovery_key_info
74+Type: text
75+_Description:
76+ Count not save recovery key:
77+ .
78+ ${ERRORMSG}
79+
80+Template: ubiquity/text/recovery_key_filename
81+Type: text
82+_Description:
83+ Enter recovery key filename
84+
85+Template: ubiquity/text/recovery_mismatch
86+Type: text
87+_Description: Passwords do not match
88+
89+Template: ubiquity/text/recovery_too_short
90+Type: text
91+_Description: Short password
92+
93+Template: ubiquity/text/recovery_weak
94+Type: text
95+_Description: Weak password
96+
97+Template: ubiquity/text/recovery_fair
98+Type: text
99+_Description: Fair password
100+
101+Template: ubiquity/text/recovery_good
102+Type: text
103+_Description: Good password
104+
105+Template: ubiquity/text/recovery_strong
106+Type: text
107+_Description: Strong password
108diff --git a/gui/gtk/stepPartCrypto.ui b/gui/gtk/stepPartCrypto.ui
109index 62b3556..89616b0 100644
110--- a/gui/gtk/stepPartCrypto.ui
111+++ b/gui/gtk/stepPartCrypto.ui
112@@ -1,6 +1,17 @@
113 <?xml version="1.0" encoding="UTF-8"?>
114+<!-- Generated with glade 3.22.2 -->
115 <interface>
116- <!-- interface-requires gtk+ 3.0 -->
117+ <requires lib="gtk+" version="3.24"/>
118+ <object class="GtkImage" id="image_file">
119+ <property name="visible">True</property>
120+ <property name="can_focus">False</property>
121+ <property name="stock">gtk-save-as</property>
122+ </object>
123+ <object class="GtkImage" id="image_generate_key">
124+ <property name="visible">True</property>
125+ <property name="can_focus">False</property>
126+ <property name="stock">gtk-refresh</property>
127+ </object>
128 <object class="GtkAlignment" id="stepPartCrypto">
129 <property name="visible">True</property>
130 <property name="can_focus">False</property>
131@@ -9,6 +20,7 @@
132 <property name="left_padding">24</property>
133 <property name="right_padding">24</property>
134 <child>
135+ <!-- n-columns=2 n-rows=11 -->
136 <object class="GtkGrid" id="crypto_grid">
137 <property name="visible">True</property>
138 <property name="can_focus">False</property>
139@@ -18,32 +30,28 @@
140 <object class="GtkLabel" id="verified_crypto_label">
141 <property name="visible">True</property>
142 <property name="can_focus">False</property>
143- <property name="xalign">1</property>
144 <property name="label" translatable="yes">Confirm the security key:</property>
145 <property name="justify">right</property>
146 <property name="single_line_mode">True</property>
147+ <property name="xalign">1</property>
148 </object>
149 <packing>
150 <property name="left_attach">0</property>
151 <property name="top_attach">3</property>
152- <property name="width">1</property>
153- <property name="height">1</property>
154 </packing>
155 </child>
156 <child>
157 <object class="GtkLabel" id="crypto_label">
158 <property name="visible">True</property>
159 <property name="can_focus">False</property>
160- <property name="xalign">1</property>
161 <property name="label" translatable="yes">Choose a security key:</property>
162 <property name="justify">right</property>
163 <property name="single_line_mode">True</property>
164+ <property name="xalign">1</property>
165 </object>
166 <packing>
167 <property name="left_attach">0</property>
168 <property name="top_attach">2</property>
169- <property name="width">1</property>
170- <property name="height">1</property>
171 </packing>
172 </child>
173 <child>
174@@ -51,15 +59,16 @@
175 <property name="visible">True</property>
176 <property name="can_focus">False</property>
177 <property name="halign">start</property>
178- <property name="xalign">0</property>
179 <property name="label" translatable="yes">Disk encryption protects your files in case you lose your computer. It requires you to enter a security key each time the computer starts up.</property>
180 <property name="wrap">True</property>
181+ <property name="width_chars">92</property>
182+ <property name="max_width_chars">92</property>
183+ <property name="xalign">0</property>
184 </object>
185 <packing>
186 <property name="left_attach">0</property>
187 <property name="top_attach">0</property>
188 <property name="width">2</property>
189- <property name="height">1</property>
190 </packing>
191 </child>
192 <child>
193@@ -67,16 +76,245 @@
194 <property name="visible">True</property>
195 <property name="can_focus">False</property>
196 <property name="halign">start</property>
197- <property name="xalign">0</property>
198- <property name="label" translatable="yes">&lt;span foreground="darkred"&gt;Warning:&lt;/span&gt; If you lose this security key, all data will be lost. If you need to, write down your key and keep it in a safe place elsewhere.</property>
199+ <property name="margin_top">6</property>
200+ <property name="label" translatable="yes">&lt;span foreground="darkred"&gt;Warning:&lt;/span&gt; If you lose your personal security key and recovery key, all data will be lost.</property>
201 <property name="use_markup">True</property>
202 <property name="wrap">True</property>
203+ <property name="width_chars">92</property>
204+ <property name="max_width_chars">92</property>
205+ <property name="xalign">0</property>
206 </object>
207 <packing>
208 <property name="left_attach">0</property>
209- <property name="top_attach">4</property>
210+ <property name="top_attach">8</property>
211 <property name="width">2</property>
212- <property name="height">1</property>
213+ </packing>
214+ </child>
215+ <child>
216+ <object class="GtkLabel" id="crypto_description_2">
217+ <property name="visible">True</property>
218+ <property name="can_focus">False</property>
219+ <property name="halign">start</property>
220+ <property name="label" translatable="yes">Any files outside of Ubuntu will not be encrypted.</property>
221+ <property name="wrap">True</property>
222+ <property name="xalign">0</property>
223+ </object>
224+ <packing>
225+ <property name="left_attach">0</property>
226+ <property name="top_attach">1</property>
227+ <property name="width">2</property>
228+ </packing>
229+ </child>
230+ <child>
231+ <!-- n-columns=3 n-rows=2 -->
232+ <object class="GtkGrid" id="password_grid">
233+ <property name="visible">True</property>
234+ <property name="can_focus">False</property>
235+ <property name="row_spacing">6</property>
236+ <property name="column_spacing">6</property>
237+ <child>
238+ <object class="GtkEntry" id="password">
239+ <property name="visible">True</property>
240+ <property name="can_focus">True</property>
241+ <property name="visibility">False</property>
242+ <property name="invisible_char">●</property>
243+ <property name="activates_default">True</property>
244+ <property name="width_chars">36</property>
245+ <signal name="changed" handler="info_loop" swapped="no"/>
246+ </object>
247+ <packing>
248+ <property name="left_attach">0</property>
249+ <property name="top_attach">0</property>
250+ </packing>
251+ </child>
252+ <child>
253+ <object class="GtkEntry" id="verified_password">
254+ <property name="visible">True</property>
255+ <property name="can_focus">True</property>
256+ <property name="visibility">False</property>
257+ <property name="invisible_char">●</property>
258+ <property name="activates_default">True</property>
259+ <property name="width_chars">36</property>
260+ <signal name="changed" handler="info_loop" swapped="no"/>
261+ </object>
262+ <packing>
263+ <property name="left_attach">0</property>
264+ <property name="top_attach">1</property>
265+ </packing>
266+ </child>
267+ <child>
268+ <object class="GtkNotebook" id="password_strength">
269+ <property name="visible">True</property>
270+ <property name="can_focus">False</property>
271+ <property name="show_tabs">False</property>
272+ <property name="show_border">False</property>
273+ <child>
274+ <object class="GtkFixed" id="password/empty">
275+ <property name="visible">True</property>
276+ <property name="can_focus">False</property>
277+ </object>
278+ </child>
279+ <child type="tab">
280+ <placeholder/>
281+ </child>
282+ <child>
283+ <object class="GtkLabel" id="password/too_short">
284+ <property name="visible">True</property>
285+ <property name="can_focus">False</property>
286+ <property name="label" translatable="yes">Short password</property>
287+ <property name="xalign">0</property>
288+ <attributes>
289+ <attribute name="scale" value="0.83333333333329995"/>
290+ <attribute name="foreground" value="#8b8b00000000"/>
291+ </attributes>
292+ </object>
293+ <packing>
294+ <property name="position">1</property>
295+ </packing>
296+ </child>
297+ <child type="tab">
298+ <placeholder/>
299+ </child>
300+ <child>
301+ <object class="GtkLabel" id="password/weak">
302+ <property name="visible">True</property>
303+ <property name="can_focus">False</property>
304+ <property name="label" translatable="yes">Weak password</property>
305+ <property name="xalign">0</property>
306+ <attributes>
307+ <attribute name="scale" value="0.83333333333329995"/>
308+ <attribute name="foreground" value="#8b8b00000000"/>
309+ </attributes>
310+ </object>
311+ <packing>
312+ <property name="position">2</property>
313+ </packing>
314+ </child>
315+ <child type="tab">
316+ <placeholder/>
317+ </child>
318+ <child>
319+ <object class="GtkLabel" id="password/fair">
320+ <property name="visible">True</property>
321+ <property name="can_focus">False</property>
322+ <property name="label" translatable="yes">Fair password</property>
323+ <property name="xalign">0</property>
324+ <attributes>
325+ <attribute name="scale" value="0.83333333333329995"/>
326+ <attribute name="foreground" value="#ffff8c8c0000"/>
327+ </attributes>
328+ </object>
329+ <packing>
330+ <property name="position">3</property>
331+ </packing>
332+ </child>
333+ <child type="tab">
334+ <placeholder/>
335+ </child>
336+ <child>
337+ <object class="GtkLabel" id="password/good">
338+ <property name="visible">True</property>
339+ <property name="can_focus">False</property>
340+ <property name="label" translatable="yes">Good password</property>
341+ <property name="xalign">0</property>
342+ <attributes>
343+ <attribute name="scale" value="0.83333333333329995"/>
344+ <attribute name="foreground" value="#000064640000"/>
345+ </attributes>
346+ </object>
347+ <packing>
348+ <property name="position">4</property>
349+ </packing>
350+ </child>
351+ <child type="tab">
352+ <placeholder/>
353+ </child>
354+ <child>
355+ <object class="GtkLabel" id="password/strong">
356+ <property name="visible">True</property>
357+ <property name="can_focus">False</property>
358+ <property name="label" translatable="yes">Strong password</property>
359+ <property name="xalign">0</property>
360+ <attributes>
361+ <attribute name="scale" value="0.83333333333329995"/>
362+ <attribute name="foreground" value="#000064640000"/>
363+ </attributes>
364+ </object>
365+ <packing>
366+ <property name="position">5</property>
367+ </packing>
368+ </child>
369+ <child type="tab">
370+ <placeholder/>
371+ </child>
372+ </object>
373+ <packing>
374+ <property name="left_attach">1</property>
375+ <property name="top_attach">0</property>
376+ </packing>
377+ </child>
378+ <child>
379+ <object class="GtkNotebook" id="password_match">
380+ <property name="visible">True</property>
381+ <property name="can_focus">False</property>
382+ <property name="show_tabs">False</property>
383+ <property name="show_border">False</property>
384+ <child>
385+ <object class="GtkFixed" id="empty2">
386+ <property name="visible">True</property>
387+ <property name="can_focus">False</property>
388+ </object>
389+ </child>
390+ <child type="tab">
391+ <placeholder/>
392+ </child>
393+ <child>
394+ <object class="GtkLabel" id="password_mismatch">
395+ <property name="visible">True</property>
396+ <property name="can_focus">False</property>
397+ <property name="label" translatable="yes">Mismatch</property>
398+ <property name="wrap">True</property>
399+ <property name="xalign">0</property>
400+ <attributes>
401+ <attribute name="scale" value="0.83333333333329995"/>
402+ <attribute name="foreground" value="#8b8b00000000"/>
403+ </attributes>
404+ </object>
405+ <packing>
406+ <property name="position">1</property>
407+ </packing>
408+ </child>
409+ <child>
410+ <object class="GtkImage" id="password_ok">
411+ <property name="visible">True</property>
412+ <property name="can_focus">False</property>
413+ <property name="xalign">0</property>
414+ <property name="stock">gtk-apply</property>
415+ </object>
416+ <packing>
417+ <property name="position">2</property>
418+ </packing>
419+ </child>
420+ <child type="tab">
421+ <placeholder/>
422+ </child>
423+ </object>
424+ <packing>
425+ <property name="left_attach">1</property>
426+ <property name="top_attach">1</property>
427+ </packing>
428+ </child>
429+ <child>
430+ <placeholder/>
431+ </child>
432+ <child>
433+ <placeholder/>
434+ </child>
435+ </object>
436+ <packing>
437+ <property name="left_attach">1</property>
438+ <property name="top_attach">2</property>
439+ <property name="height">2</property>
440 </packing>
441 </child>
442 <child>
443@@ -84,120 +322,172 @@
444 <property name="visible">True</property>
445 <property name="can_focus">False</property>
446 <property name="halign">end</property>
447- <property name="xalign">0</property>
448 <property name="label" translatable="yes">For more security:</property>
449 <property name="justify">right</property>
450+ <property name="xalign">0</property>
451 </object>
452 <packing>
453 <property name="left_attach">0</property>
454- <property name="top_attach">5</property>
455- <property name="width">1</property>
456- <property name="height">1</property>
457+ <property name="top_attach">9</property>
458 </packing>
459 </child>
460 <child>
461 <object class="GtkCheckButton" id="crypto_overwrite_space">
462- <property name="label" translatable="yes">Overwrite the available space first</property>
463+ <property name="label" translatable="yes">Overwrite the available space first.</property>
464 <property name="use_action_appearance">False</property>
465 <property name="visible">True</property>
466 <property name="can_focus">True</property>
467 <property name="receives_default">False</property>
468- <property name="use_action_appearance">False</property>
469 <property name="xalign">0</property>
470 <property name="draw_indicator">True</property>
471 </object>
472 <packing>
473 <property name="left_attach">1</property>
474- <property name="top_attach">5</property>
475- <property name="width">1</property>
476- <property name="height">1</property>
477+ <property name="top_attach">9</property>
478 </packing>
479 </child>
480 <child>
481- <object class="GtkLabel" id="crypto_extra_time">
482+ <object class="GtkLabel" id="recovery_key_warning">
483 <property name="visible">True</property>
484 <property name="can_focus">False</property>
485- <property name="margin_left">24</property>
486+ <property name="halign">start</property>
487+ <property name="margin_top">6</property>
488+ <property name="label" translatable="yes">A recovery key is generated and will be temporarily saved on the live system. You can enter your own and can select an alternate location. Save this file and keep it in a safe place elsewhere before rebooting. </property>
489+ <property name="wrap">True</property>
490+ <property name="width_chars">72</property>
491+ <property name="max_width_chars">72</property>
492 <property name="xalign">0</property>
493- <property name="label" translatable="yes">&lt;span weight="light" size="small"&gt;The installation may take much longer.&lt;/span&gt;</property>
494- <property name="use_markup">True</property>
495- <property name="single_line_mode">True</property>
496 </object>
497 <packing>
498 <property name="left_attach">1</property>
499- <property name="top_attach">6</property>
500- <property name="width">1</property>
501- <property name="height">1</property>
502+ <property name="top_attach">4</property>
503 </packing>
504 </child>
505 <child>
506- <object class="GtkLabel" id="crypto_description_2">
507+ <object class="GtkLabel" id="recovery_key_location_label">
508 <property name="visible">True</property>
509 <property name="can_focus">False</property>
510- <property name="halign">start</property>
511- <property name="xalign">0</property>
512- <property name="label" translatable="yes">Any files outside of Ubuntu will not be encrypted.</property>
513- <property name="wrap">True</property>
514+ <property name="label" translatable="yes">Location:</property>
515+ <property name="justify">right</property>
516+ <property name="single_line_mode">True</property>
517+ <property name="xalign">1</property>
518 </object>
519 <packing>
520 <property name="left_attach">0</property>
521- <property name="top_attach">1</property>
522- <property name="width">2</property>
523- <property name="height">1</property>
524+ <property name="top_attach">7</property>
525 </packing>
526 </child>
527 <child>
528- <object class="GtkGrid" id="password_grid">
529+ <object class="GtkLabel" id="recovery_key_label">
530+ <property name="visible">True</property>
531+ <property name="can_focus">False</property>
532+ <property name="label" translatable="yes">Recovery key:</property>
533+ <property name="justify">right</property>
534+ <property name="single_line_mode">True</property>
535+ <property name="xalign">1</property>
536+ </object>
537+ <packing>
538+ <property name="left_attach">0</property>
539+ <property name="top_attach">5</property>
540+ </packing>
541+ </child>
542+ <child>
543+ <object class="GtkLabel" id="verified_recovery_key_label">
544+ <property name="visible">True</property>
545+ <property name="can_focus">False</property>
546+ <property name="label" translatable="yes">Confirm the recovery key:</property>
547+ <property name="justify">right</property>
548+ <property name="single_line_mode">True</property>
549+ <property name="xalign">1</property>
550+ </object>
551+ <packing>
552+ <property name="left_attach">0</property>
553+ <property name="top_attach">6</property>
554+ </packing>
555+ </child>
556+ <child>
557+ <object class="GtkCheckButton" id="recovery_key_enable">
558+ <property name="label" translatable="yes">Enable recovery key</property>
559+ <property name="visible">True</property>
560+ <property name="can_focus">True</property>
561+ <property name="receives_default">False</property>
562+ <property name="valign">start</property>
563+ <property name="margin_top">6</property>
564+ <property name="draw_indicator">True</property>
565+ <signal name="toggled" handler="on_recovery_key_enable_toggled" swapped="no"/>
566+ </object>
567+ <packing>
568+ <property name="left_attach">0</property>
569+ <property name="top_attach">4</property>
570+ </packing>
571+ </child>
572+ <child>
573+ <!-- n-columns=3 n-rows=3 -->
574+ <object class="GtkGrid" id="recovery_grid">
575 <property name="visible">True</property>
576 <property name="can_focus">False</property>
577 <property name="row_spacing">6</property>
578 <property name="column_spacing">6</property>
579 <child>
580- <object class="GtkEntry" id="password">
581+ <object class="GtkEntry" id="recovery_key">
582 <property name="visible">True</property>
583 <property name="can_focus">True</property>
584- <property name="hexpand">True</property>
585 <property name="visibility">False</property>
586 <property name="invisible_char">●</property>
587 <property name="activates_default">True</property>
588- <property name="width_chars">20</property>
589- <property name="invisible_char_set">True</property>
590+ <property name="width_chars">36</property>
591+ <property name="secondary_icon_name">view-reveal-symbolic</property>
592+ <property name="primary_icon_activatable">False</property>
593+ <property name="primary_icon_sensitive">False</property>
594+ <property name="secondary_icon_tooltip_text" translatable="yes"> </property>
595+ <property name="secondary_icon_tooltip_markup" translatable="yes"> </property>
596 <signal name="changed" handler="info_loop" swapped="no"/>
597+ <signal name="icon_press" handler="on_recovery_key_toggle_visibility" swapped="no"/>
598 </object>
599 <packing>
600 <property name="left_attach">0</property>
601 <property name="top_attach">0</property>
602- <property name="width">1</property>
603- <property name="height">1</property>
604 </packing>
605 </child>
606 <child>
607- <object class="GtkEntry" id="verified_password">
608+ <object class="GtkButton" id="recovery_key_generate_button">
609+ <property name="visible">True</property>
610+ <property name="can_focus">True</property>
611+ <property name="receives_default">True</property>
612+ <property name="image">image_generate_key</property>
613+ <signal name="clicked" handler="on_recovery_key_generate_button" swapped="no"/>
614+ </object>
615+ <packing>
616+ <property name="left_attach">1</property>
617+ <property name="top_attach">0</property>
618+ </packing>
619+ </child>
620+ <child>
621+ <object class="GtkEntry" id="verified_recovery_key">
622 <property name="visible">True</property>
623 <property name="can_focus">True</property>
624- <property name="hexpand">True</property>
625 <property name="visibility">False</property>
626 <property name="invisible_char">●</property>
627 <property name="activates_default">True</property>
628- <property name="width_chars">20</property>
629- <property name="invisible_char_set">True</property>
630+ <property name="width_chars">36</property>
631+ <property name="primary_icon_activatable">False</property>
632+ <property name="primary_icon_sensitive">False</property>
633 <signal name="changed" handler="info_loop" swapped="no"/>
634 </object>
635 <packing>
636 <property name="left_attach">0</property>
637 <property name="top_attach">1</property>
638- <property name="width">1</property>
639- <property name="height">1</property>
640 </packing>
641 </child>
642 <child>
643- <object class="GtkNotebook" id="password_strength">
644+ <object class="GtkNotebook" id="recovery_strength">
645 <property name="visible">True</property>
646 <property name="can_focus">False</property>
647+ <property name="hexpand">True</property>
648 <property name="show_tabs">False</property>
649 <property name="show_border">False</property>
650 <child>
651- <object class="GtkFixed" id="empty">
652+ <object class="GtkFixed" id="recovery/empty">
653 <property name="visible">True</property>
654 <property name="can_focus">False</property>
655 </object>
656@@ -206,11 +496,11 @@
657 <placeholder/>
658 </child>
659 <child>
660- <object class="GtkLabel" id="password/too_short">
661+ <object class="GtkLabel" id="recovery_too_short">
662 <property name="visible">True</property>
663 <property name="can_focus">False</property>
664- <property name="xalign">0</property>
665 <property name="label" translatable="yes">Short password</property>
666+ <property name="xalign">0</property>
667 <attributes>
668 <attribute name="scale" value="0.83333333333329995"/>
669 <attribute name="foreground" value="#8b8b00000000"/>
670@@ -224,11 +514,11 @@
671 <placeholder/>
672 </child>
673 <child>
674- <object class="GtkLabel" id="password/weak">
675+ <object class="GtkLabel" id="recovery_weak">
676 <property name="visible">True</property>
677 <property name="can_focus">False</property>
678- <property name="xalign">0</property>
679 <property name="label" translatable="yes">Weak password</property>
680+ <property name="xalign">0</property>
681 <attributes>
682 <attribute name="scale" value="0.83333333333329995"/>
683 <attribute name="foreground" value="#8b8b00000000"/>
684@@ -242,11 +532,11 @@
685 <placeholder/>
686 </child>
687 <child>
688- <object class="GtkLabel" id="password/fair">
689+ <object class="GtkLabel" id="recovery_fair">
690 <property name="visible">True</property>
691 <property name="can_focus">False</property>
692- <property name="xalign">0</property>
693 <property name="label" translatable="yes">Fair password</property>
694+ <property name="xalign">0</property>
695 <attributes>
696 <attribute name="scale" value="0.83333333333329995"/>
697 <attribute name="foreground" value="#ffff8c8c0000"/>
698@@ -260,11 +550,11 @@
699 <placeholder/>
700 </child>
701 <child>
702- <object class="GtkLabel" id="password/good">
703+ <object class="GtkLabel" id="recovery_good">
704 <property name="visible">True</property>
705 <property name="can_focus">False</property>
706- <property name="xalign">0</property>
707 <property name="label" translatable="yes">Good password</property>
708+ <property name="xalign">0</property>
709 <attributes>
710 <attribute name="scale" value="0.83333333333329995"/>
711 <attribute name="foreground" value="#000064640000"/>
712@@ -278,11 +568,11 @@
713 <placeholder/>
714 </child>
715 <child>
716- <object class="GtkLabel" id="password/strong">
717+ <object class="GtkLabel" id="recovery_strong">
718 <property name="visible">True</property>
719 <property name="can_focus">False</property>
720- <property name="xalign">0</property>
721 <property name="label" translatable="yes">Strong password</property>
722+ <property name="xalign">0</property>
723 <attributes>
724 <attribute name="scale" value="0.83333333333329995"/>
725 <attribute name="foreground" value="#000064640000"/>
726@@ -297,20 +587,19 @@
727 </child>
728 </object>
729 <packing>
730- <property name="left_attach">1</property>
731+ <property name="left_attach">2</property>
732 <property name="top_attach">0</property>
733- <property name="width">1</property>
734- <property name="height">1</property>
735 </packing>
736 </child>
737 <child>
738- <object class="GtkNotebook" id="password_match">
739+ <object class="GtkNotebook" id="recovery_match">
740 <property name="visible">True</property>
741 <property name="can_focus">False</property>
742+ <property name="hexpand">True</property>
743 <property name="show_tabs">False</property>
744 <property name="show_border">False</property>
745 <child>
746- <object class="GtkFixed" id="empty2">
747+ <object class="GtkFixed" id="recovery_empty2">
748 <property name="visible">True</property>
749 <property name="can_focus">False</property>
750 </object>
751@@ -319,11 +608,12 @@
752 <placeholder/>
753 </child>
754 <child>
755- <object class="GtkLabel" id="password_mismatch">
756+ <object class="GtkLabel" id="recovery_mismatch">
757 <property name="visible">True</property>
758 <property name="can_focus">False</property>
759- <property name="xalign">0</property>
760 <property name="label" translatable="yes">Mismatch</property>
761+ <property name="wrap">True</property>
762+ <property name="xalign">0</property>
763 <attributes>
764 <attribute name="scale" value="0.83333333333329995"/>
765 <attribute name="foreground" value="#8b8b00000000"/>
766@@ -334,7 +624,7 @@
767 </packing>
768 </child>
769 <child>
770- <object class="GtkImage" id="password_ok">
771+ <object class="GtkImage" id="recovery_ok">
772 <property name="visible">True</property>
773 <property name="can_focus">False</property>
774 <property name="xalign">0</property>
775@@ -349,18 +639,78 @@
776 </child>
777 </object>
778 <packing>
779- <property name="left_attach">1</property>
780+ <property name="left_attach">2</property>
781 <property name="top_attach">1</property>
782- <property name="width">1</property>
783- <property name="height">1</property>
784 </packing>
785 </child>
786+ <child>
787+ <object class="GtkLabel" id="recovery_key_location">
788+ <property name="visible">True</property>
789+ <property name="can_focus">False</property>
790+ <property name="label">/home/ubuntu/recovery.key</property>
791+ <property name="ellipsize">end</property>
792+ <property name="width_chars">38</property>
793+ <property name="single_line_mode">True</property>
794+ <property name="max_width_chars">38</property>
795+ <property name="track_visited_links">False</property>
796+ <property name="xalign">0.05000000074505806</property>
797+ </object>
798+ <packing>
799+ <property name="left_attach">0</property>
800+ <property name="top_attach">2</property>
801+ </packing>
802+ </child>
803+ <child>
804+ <object class="GtkButton" id="recovery_key_button">
805+ <property name="visible">True</property>
806+ <property name="can_focus">True</property>
807+ <property name="receives_default">True</property>
808+ <property name="image">image_file</property>
809+ <property name="always_show_image">True</property>
810+ <signal name="clicked" handler="on_recovery_key_button_clicked" swapped="no"/>
811+ </object>
812+ <packing>
813+ <property name="left_attach">1</property>
814+ <property name="top_attach">2</property>
815+ </packing>
816+ </child>
817+ <child>
818+ <object class="GtkLabel" id="recovery_key_location_warning">
819+ <property name="visible">False</property>
820+ <property name="can_focus">False</property>
821+ <property name="wrap">True</property>
822+ <property name="width_chars">32</property>
823+ <property name="max_width_chars">32</property>
824+ <property name="track_visited_links">False</property>
825+ </object>
826+ <packing>
827+ <property name="left_attach">2</property>
828+ <property name="top_attach">2</property>
829+ </packing>
830+ </child>
831+ <child>
832+ <placeholder/>
833+ </child>
834 </object>
835 <packing>
836 <property name="left_attach">1</property>
837- <property name="top_attach">2</property>
838- <property name="width">1</property>
839- <property name="height">2</property>
840+ <property name="top_attach">5</property>
841+ <property name="height">3</property>
842+ </packing>
843+ </child>
844+ <child>
845+ <object class="GtkLabel" id="crypto_extra_time">
846+ <property name="visible">True</property>
847+ <property name="can_focus">False</property>
848+ <property name="margin_left">24</property>
849+ <property name="label" translatable="yes">&lt;span weight="light" size="small"&gt;The installation may take much longer.&lt;/span&gt;</property>
850+ <property name="use_markup">True</property>
851+ <property name="single_line_mode">True</property>
852+ <property name="xalign">0</property>
853+ </object>
854+ <packing>
855+ <property name="left_attach">1</property>
856+ <property name="top_attach">10</property>
857 </packing>
858 </child>
859 <child>
860diff --git a/scripts/plugininstall.py b/scripts/plugininstall.py
861index f7d5a7f..cd46373 100755
862--- a/scripts/plugininstall.py
863+++ b/scripts/plugininstall.py
864@@ -234,6 +234,7 @@ class Install(install_misc.InstallBase):
865 self.next_region()
866 self.db.progress('INFO', 'ubiquity/install/bootloader')
867 self.copy_mok()
868+ self.configure_recovery_key()
869 self.configure_bootloader()
870
871 self.next_region(size=4)
872@@ -899,6 +900,56 @@ class Install(install_misc.InstallBase):
873 continue
874 os.symlink(linksrc, linkdst)
875
876+ def configure_recovery_key(self):
877+ crypto_key = self.db.get('ubiquity/crypto_key')
878+ recovery_key = self.db.get('ubiquity/recovery_key')
879+ if not crypto_key or not recovery_key:
880+ self.clean_crypto_keys()
881+ return
882+
883+ debconf_disk = self.db.get('partman-auto/select_disk')
884+ disk = debconf_disk.split('/')[-1].replace('=', '/')
885+
886+ args = ['lsblk', '-lp', '-oNAME,FSTYPE', disk]
887+ lsblk_out = subprocess.check_output(args).decode(sys.stdout.encoding)
888+ for line in lsblk_out.splitlines():
889+ if 'crypto_LUKS' not in line:
890+ continue
891+ dev = line.split()[0]
892+
893+ if not dev:
894+ syslog.syslog(syslog.LOG_ERR, ' '.join(args))
895+ syslog.syslog(syslog.LOG_ERR, 'determining crypto device failed. Output: %s' % lsblk_out)
896+ self.clean_crypto_keys()
897+ self.db.input('critical', 'ubiquity/install/broken_luks_add_key')
898+ self.db.go()
899+ return
900+ syslog.syslog(' '.join(args))
901+
902+ key_args = "%s\n%s" % (crypto_key, recovery_key)
903+ try:
904+ log_args = ['log-output', '-t', 'ubiquity']
905+ log_args.extend(['cryptsetup', 'luksAddKey', dev])
906+ p = subprocess.run(log_args, input=key_args, encoding="utf-8")
907+ except subprocess.CalledProcessError as e:
908+ syslog.syslog(syslog.LOG_ERR, ' '.join(log_args))
909+ syslog.syslog(syslog.LOG_ERR, "cryptsetup failed(%s): %s" % (e.returncode, e.output))
910+ return
911+ finally:
912+ self.clean_crypto_keys()
913+
914+ if p.returncode != 0:
915+ syslog.syslog(syslog.LOG_ERR, ' '.join(log_args))
916+ self.db.input('critical', 'ubiquity/install/broken_luks_add_key')
917+ self.db.go()
918+ return
919+
920+ syslog.syslog(' '.join(log_args))
921+
922+ def clean_crypto_keys(self):
923+ self.db.set('ubiquity/crypto_key', '')
924+ self.db.set('ubiquity/recovery_key', '')
925+
926 def configure_bootloader(self):
927 """Configure and install the boot loader."""
928 if 'UBIQUITY_OEM_USER_CONFIG' in os.environ:
929diff --git a/tests/test_gtkui.py b/tests/test_gtkui.py
930index 60cbfd3..a68395e 100644
931--- a/tests/test_gtkui.py
932+++ b/tests/test_gtkui.py
933@@ -73,7 +73,7 @@ class TestFrontend(unittest.TestCase):
934 # Anything smaller will need to use Alt+Ctrl+Pgd/Right
935 # Scrollbars anyone?
936 # self.assertLessEqual(alloc.width, 640, page.module.NAME) # fixme
937- self.assertLessEqual(alloc.height, 556, page.module.NAME)
938+ self.assertLessEqual(alloc.height, 744, page.module.NAME) # 768 - 24px (top panel)
939 if page.module.NAME == 'partman':
940 ui.allow_change_step(False)
941
942@@ -123,6 +123,7 @@ class TestFrontend(unittest.TestCase):
943 # setup page.
944 'password_strength', 'hostname_error_label',
945 'password_error_label', 'username_error_label',
946+ 'recovery_strength',
947 # Pulled straight from debconf into the UI on progress.
948 'install_progress_text',
949 # Contains just the traceback.
950@@ -132,6 +133,7 @@ class TestFrontend(unittest.TestCase):
951 'page_title',
952 # To be calculated and set
953 'partition_lvm_status',
954+ 'recovery_key_location',
955 # These are "placeholders" for debconfs impromptu notices
956 'ubi_question_dialog', 'question_label',
957 # Calculated error string
958diff --git a/ubiquity/components/plugininstall.py b/ubiquity/components/plugininstall.py
959index dcb04d6..6aa1a90 100644
960--- a/ubiquity/components/plugininstall.py
961+++ b/ubiquity/components/plugininstall.py
962@@ -67,6 +67,8 @@ class Install(FilteredCommand):
963 fatal = False
964 elif question == 'ubiquity/install/broken_active_directory':
965 fatal = False
966+ elif question == 'ubiquity/install/broken_luks_add_key':
967+ fatal = False
968 else:
969 fatal = True
970 self.frontend.error_dialog(self.description(question),
971diff --git a/ubiquity/misc.py b/ubiquity/misc.py
972index e9c2a2b..5fcaf19 100644
973--- a/ubiquity/misc.py
974+++ b/ubiquity/misc.py
975@@ -9,6 +9,7 @@ import re
976 import shutil
977 import subprocess
978 import syslog
979+import json
980
981 from ubiquity import osextras
982 from gi.repository import Gio, GLib, GObject
983@@ -150,6 +151,14 @@ def raise_privileges(func):
984 return helper
985
986
987+def get_live_user_home():
988+ """Returns live user home directory, even if executed under SUDO or PKEXEC"""
989+ uid = os.environ.get('PKEXEC_UID', os.environ.get('SUDO_UID'))
990+ if uid is not None:
991+ return pwd.getpwuid(int(uid)).pw_dir
992+ return os.getenv('HOME', '')
993+
994+
995 @raise_privileges
996 def grub_options():
997 """ Generates a list of suitable targets for grub-installer
998@@ -957,6 +966,34 @@ def launch_uri(uri):
999 preexec_fn=drop_all_privileges)
1000
1001
1002+def is_removable_device(path):
1003+ """Returns True if path is on a removable device"""
1004+ lsblk_output = ""
1005+ cmd = "lsblk -J -o MOUNTPOINT,PATH,RM"
1006+
1007+ # Find mount point of path
1008+ mp = path
1009+ while not os.path.ismount(mp):
1010+ mp = os.path.dirname(mp)
1011+
1012+ # In ubiquity environment / is the installation media
1013+ if mp == "/":
1014+ return True
1015+
1016+ # Then search if the corresponding device is removable
1017+ try:
1018+ lsblk_output = subprocess.check_output(cmd.split())
1019+ except subprocess.CalledProcessError:
1020+ syslog.syslog(syslog.LOG_ERR, "Unable to determine if %s is on a removable device" % path)
1021+ return False
1022+
1023+ devices = json.loads(lsblk_output)
1024+ for entry in devices["blockdevices"]:
1025+ if entry["mountpoint"] == mp and entry["rm"]:
1026+ return True
1027+ return False
1028+
1029+
1030 class SystemdUnitWatcher:
1031 def __init__(self, unit, cb):
1032 # try connecting to the bus
1033diff --git a/ubiquity/plugins/ubi-partman.py b/ubiquity/plugins/ubi-partman.py
1034index 68a1140..83cab1b 100644
1035--- a/ubiquity/plugins/ubi-partman.py
1036+++ b/ubiquity/plugins/ubi-partman.py
1037@@ -110,6 +110,9 @@ class PageBase(plugin.PluginUI):
1038 def get_crypto_keys(self):
1039 pass
1040
1041+ def get_recovery_keys(self):
1042+ pass
1043+
1044
1045 class PageGtk(PageBase):
1046 plugin_title = 'ubiquity/text/part_auto_heading_label'
1047@@ -145,7 +148,7 @@ class PageGtk(PageBase):
1048 for wdg in all_widgets:
1049 setattr(self, wdg, builder.get_object(wdg))
1050
1051- # Crypto page
1052+ # Crypto page, used for both primary and recovery keys
1053 self.password_strength_pages = {
1054 'empty': 0,
1055 'too_short': 1,
1056@@ -210,6 +213,14 @@ class PageGtk(PageBase):
1057 # Define a list to save grub imformation
1058 self.grub_options = []
1059
1060+ default_recovery_key_location = os.path.join(misc.get_live_user_home(), 'recovery.key')
1061+ self.recovery_key_location.set_text(default_recovery_key_location)
1062+ self.recovery_key.set_visibility(False)
1063+ self.recovery_key.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, 'view-reveal-symbolic')
1064+ self.verified_recovery_key.set_visibility(False)
1065+ self.recovery_key_location_warning.set_visible(False)
1066+ self.enable_recovery_key(False)
1067+
1068 def on_link_clicked(self, widget, uri):
1069 misc.launch_uri(uri)
1070
1071@@ -275,7 +286,13 @@ class PageGtk(PageBase):
1072 return
1073 crypto_widgets += [
1074 ('verified_crypto_label', 'crypto_label', 'bottom', 1, 1),
1075- ('crypto_warning', 'verified_crypto_label', 'bottom', 2, 1),
1076+ ('recovery_key_enable', 'verified_crypto_label', 'bottom', 1, 1),
1077+ ('recovery_key_warning', 'recovery_key_enable', 'right', 1, 1),
1078+ ('recovery_grid', 'recovery_key_warning', 'bottom', 1, 3),
1079+ ('recovery_key_label', 'recovery_grid', 'left', 1, 1),
1080+ ('verified_recovery_key_label', 'recovery_key_label', 'bottom', 1, 1),
1081+ ('recovery_key_location_label', 'verified_recovery_key_label', 'bottom', 1, 1),
1082+ ('crypto_warning', 'recovery_key_location_label', 'bottom', 2, 1),
1083 ('crypto_extra_label', 'crypto_warning', 'bottom', 1, 1),
1084 ('crypto_overwrite_space', 'crypto_extra_label', 'right', 1, 1),
1085 ('crypto_extra_time', 'crypto_overwrite_space', 'bottom', 1, 1)]
1086@@ -291,6 +308,14 @@ class PageGtk(PageBase):
1087 width, height)
1088 widget.show()
1089
1090+ def generate_recovery_key(self):
1091+ if not self.recovery_key_enable.get_active():
1092+ return
1093+ from secrets import randbelow
1094+ key = str(randbelow(10**48)).zfill(48)
1095+ self.recovery_key.set_text(key)
1096+ self.verified_recovery_key.set_text(key)
1097+
1098 def on_advanced_features_clicked(self, widget):
1099 from gi.repository import Gtk
1100
1101@@ -329,6 +354,77 @@ class PageGtk(PageBase):
1102 selected.set_active(True)
1103 self.use_crypto.set_active(crypto_selected)
1104
1105+ def on_recovery_key_button_clicked(self, widget):
1106+ from gi.repository import Gtk
1107+ label = self.controller.get_string('recovery_key_filename')
1108+
1109+ # Set HOME to the live session user's home directory so the
1110+ # filechooser dialog opens at the right location.
1111+ orig_home = os.getenv('HOME')
1112+ live_user_home = misc.get_live_user_home()
1113+ if live_user_home:
1114+ os.environ['HOME'] = live_user_home
1115+ save_recovery_dialog = Gtk.FileChooserDialog(label, widget.get_toplevel(),
1116+ Gtk.FileChooserAction.SAVE,
1117+ (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
1118+ Gtk.STOCK_OPEN, Gtk.ResponseType.ACCEPT))
1119+ save_recovery_dialog.set_do_overwrite_confirmation(True)
1120+ save_recovery_dialog.set_modal(True)
1121+ save_recovery_dialog.set_current_name(os.path.basename(self.recovery_key_location.get_text()))
1122+ save_recovery_dialog.set_filename(self.recovery_key_location.get_text())
1123+ save_recovery_dialog.connect("response", self.on_save_recovery_selected)
1124+ save_recovery_dialog.remove_shortcut_folder('/root')
1125+ save_recovery_dialog.show()
1126+ if orig_home is not None:
1127+ os.environ['HOME'] = orig_home
1128+ else:
1129+ del os.environ['HOME']
1130+
1131+ def on_save_recovery_selected(self, dialog, response_id):
1132+ from gi.repository import Gtk
1133+ if response_id == Gtk.ResponseType.ACCEPT:
1134+ self.recovery_key_location.set_text(dialog.get_filename())
1135+ dialog.destroy()
1136+
1137+ is_removable = misc.is_removable_device(self.recovery_key_location.get_text())
1138+ self.recovery_key_location_warning.set_visible(not is_removable)
1139+
1140+ def on_recovery_key_generate_button(self, widget):
1141+ self.generate_recovery_key()
1142+
1143+ def on_recovery_key_toggle_visibility(self, widget, icon_pos, event):
1144+ from gi.repository import Gtk
1145+ visibility = self.recovery_key.get_visibility()
1146+ self.recovery_key.set_visibility(not visibility)
1147+ self.verified_recovery_key.set_visibility(not visibility)
1148+ self.recovery_key.set_icon_from_icon_name(
1149+ Gtk.EntryIconPosition.SECONDARY, ('view-conceal-symbolic', 'view-reveal-symbolic')[visibility])
1150+
1151+ def on_recovery_key_enable_toggled(self, widget):
1152+ self.enable_recovery_key(widget.get_active())
1153+
1154+ def enable_recovery_key(self, enable=False):
1155+ self.recovery_key_warning.set_sensitive(enable)
1156+ self.recovery_key_label.set_sensitive(enable)
1157+ self.recovery_key.set_sensitive(enable)
1158+ self.recovery_key_generate_button.set_sensitive(enable)
1159+ self.verified_recovery_key_label.set_sensitive(enable)
1160+ self.verified_recovery_key.set_sensitive(enable)
1161+ self.recovery_key_location_label.set_sensitive(enable)
1162+ self.recovery_key_location_warning.set_sensitive(enable)
1163+ self.recovery_key_location.set_sensitive(enable)
1164+ self.recovery_key_button.set_sensitive(enable)
1165+
1166+ if enable:
1167+ self.generate_recovery_key()
1168+ else:
1169+ self.recovery_key.set_text("")
1170+ self.verified_recovery_key.set_text("")
1171+ self.recovery_strength.set_current_page(
1172+ self.password_strength_pages['empty'])
1173+ self.recovery_match.set_current_page(
1174+ self.password_match_pages['empty'])
1175+
1176 def should_show_bitlocker_page(self):
1177 return ('bitlocker' in self.extra_options or
1178 os.environ.get('SHOW_BITLOCKER_UI', '0') == '1')
1179@@ -436,6 +532,24 @@ class PageGtk(PageBase):
1180 self.plugin_is_install = True
1181 return True
1182
1183+ recovery_key_location_path = self.recovery_key_location.get_text()
1184+ if recovery_key_location_path:
1185+ try:
1186+ with open(recovery_key_location_path, "w") as f:
1187+ f.write(self.recovery_key.get_text())
1188+ except Exception as exc:
1189+ save_recovery_key_info = 'ubiquity/text/save_recovery_key_info'
1190+ msg = self.controller.get_string(save_recovery_key_info).replace('${ERRORMSG}', str(exc))
1191+
1192+ from gi.repository import Gtk
1193+ dialog = Gtk.MessageDialog(
1194+ self.current_page.get_toplevel(), Gtk.DialogFlags.MODAL,
1195+ Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE, None)
1196+ dialog.set_markup(msg)
1197+ dialog.run()
1198+ dialog.destroy()
1199+ return True
1200+
1201 # Return control to partman, which will call
1202 # get_autopartition_choice and start partitioninging the device.
1203 self.controller.switch_to_install_interface()
1204@@ -1014,9 +1128,17 @@ class PageGtk(PageBase):
1205 self.partition_dialog_okbutton.set_sensitive(True)
1206
1207 for widget in ['password_grid', 'crypto_label', 'crypto_warning',
1208- 'verified_crypto_label', 'crypto_extra_label',
1209- 'crypto_overwrite_space', 'crypto_extra_time']:
1210+ 'verified_crypto_label',
1211+ 'crypto_extra_label',
1212+ 'crypto_overwrite_space', 'crypto_extra_time',
1213+ 'recovery_key_enable', 'recovery_key_warning',
1214+ 'recovery_grid',
1215+ 'recovery_key_label',
1216+ 'verified_recovery_key_label',
1217+ 'recovery_key_location_label']:
1218 getattr(getattr(self, widget), action)()
1219+ is_removable = misc.is_removable_device(self.recovery_key_location.get_text())
1220+ self.recovery_key_location_warning.set_visible(not is_removable)
1221
1222 @plugin.only_this_page
1223 def partman_dialog(self, devpart, partition, create=True):
1224@@ -1553,6 +1675,28 @@ class PageGtk(PageBase):
1225 self.password_strength.set_current_page(
1226 self.password_strength_pages['empty'])
1227
1228+ # Recovery key
1229+ recovery = self.recovery_key.get_text()
1230+ vrecovery = self.verified_recovery_key.get_text()
1231+
1232+ if recovery:
1233+ if recovery != vrecovery:
1234+ # It's okay to reuse complete since it'll stay False if it's
1235+ # already false from previous check and switch to False
1236+ # otherwise.
1237+ # In either case, we don't want to proceed if the password or
1238+ # the recovery are invalid.
1239+ complete = False
1240+ self.recovery_match.set_current_page(
1241+ self.password_match_pages['mismatch'])
1242+ else:
1243+ self.recovery_match.set_current_page(
1244+ self.password_match_pages['ok'])
1245+
1246+ txt = validation.human_password_strength(recovery)[0]
1247+ self.recovery_strength.set_current_page(
1248+ self.password_strength_pages[txt])
1249+
1250 self.controller.allow_go_forward(complete)
1251 self.partition_dialog_okbutton.set_sensitive(complete)
1252 return complete
1253@@ -1573,6 +1717,12 @@ class PageGtk(PageBase):
1254 else:
1255 return False
1256
1257+ def get_recovery_keys(self):
1258+ if self.info_loop(None):
1259+ return self.recovery_key.get_text()
1260+ else:
1261+ return False
1262+
1263
1264 class PageKde(PageBase):
1265 plugin_breadcrumb = 'ubiquity/text/breadcrumb_partition'
1266@@ -3234,6 +3384,8 @@ class Page(plugin.Plugin):
1267
1268 if do_preseed:
1269 self.preseed(question, self.ui.get_crypto_keys())
1270+ self.preseed('ubiquity/crypto_key', self.ui.get_crypto_keys())
1271+ self.preseed('ubiquity/recovery_key', self.ui.get_recovery_keys())
1272 return True
1273
1274 elif question == 'partman-crypto/mainmenu':
1275diff --git a/ubiquity/validation.py b/ubiquity/validation.py
1276index 9a08b4e..a782acc 100644
1277--- a/ubiquity/validation.py
1278+++ b/ubiquity/validation.py
1279@@ -116,6 +116,12 @@ def password_strength(password):
1280 strength = 1
1281 if strength < 0:
1282 strength = 0
1283+
1284+ # Recovery keys are 48 digits number and cannot be considered "fair"
1285+ # so set it a level higher
1286+ if len(password) >= 48 and strength < 0.75:
1287+ strength = 0.8
1288+
1289 return strength
1290
1291

Subscribers

People subscribed via source and target branches