1 /*
2  * Copyright (C) 2018 Rafael Ostertag
3  *
4  * This file is part of YAPET.
5  *
6  * YAPET is free software: you can redistribute it and/or modify it under the
7  * terms of the GNU General Public License as published by the Free Software
8  * Foundation, either version 3 of the License, or (at your option) any later
9  * version.
10  *
11  * YAPET is distributed in the hope that it will be useful, but WITHOUT ANY
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
14  * details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * YAPET.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  * Additional permission under GNU GPL version 3 section 7
20  *
21  * If you modify this program, or any covered work, by linking or combining it
22  * with the OpenSSL project's OpenSSL library (or a modified version of that
23  * library), containing parts covered by the terms of the OpenSSL or SSLeay
24  * licenses, Rafael Ostertag grants you additional permission to convey the
25  * resulting work.  Corresponding Source for a non-source form of such a
26  * combination shall include the source code for the parts of OpenSSL used as
27  * well as that of the covered work.
28  */
29 
30 #include <cassert>
31 #include <cstdio>
32 
33 #include "cryptofactoryhelper.hh"
34 #include "file.h"
35 #include "fileerror.hh"
36 #include "globals.h"
37 #include "intl.h"
38 #include "promptpassword.h"
39 #include "utils.hh"
40 #include "yapeterror.hh"
41 
42 //
43 // Private
44 //
45 
window_close_handler(YACURS::Event & e)46 void PromptPassword::window_close_handler(YACURS::Event& e) {
47     assert(e == YACURS::EVT_WINDOW_CLOSE);
48 
49     YACURS::EventEx<YACURS::WindowBase*>& evt =
50         dynamic_cast<YACURS::EventEx<YACURS::WindowBase*>&>(e);
51 
52     if (pwdialog != nullptr && evt.data() == pwdialog) {
53         if (pwdialog->dialog_state() == YACURS::DIALOG_OK) {
54             try {
55                 yapet::SecureArray password{
56                     yapet::toSecureArray(pwdialog->password().c_str())};
57 
58                 std::shared_ptr<yapet::AbstractCryptoFactory> cryptoFactory{
59                     yapet::getCryptoFactoryForFile(_filename, password)};
60 
61                 if (!cryptoFactory) {
62                     char msg[YAPET::Consts::EXCEPTION_MESSAGE_BUFFER_SIZE];
63                     std::snprintf(
64                         msg, YAPET::Consts::EXCEPTION_MESSAGE_BUFFER_SIZE,
65                         _("File '%s' not recognized"), _filename.c_str());
66                     throw yapet::FileFormatError{msg};
67                 }
68 
69                 // This will raise an exception if password is wrong
70                 YAPET::File{cryptoFactory, _filename, false,
71                             YAPET::Globals::config.filesecurity};
72 
73                 // We were able to open the file with the given password,
74                 // remember that cryptFactory
75                 _cryptoFactory = cryptoFactory;
76                 YACURS::EventQueue::submit(YACURS::EventEx<PromptPassword*>(
77                     YAPET::EVT_APOPTOSIS, this));
78             } catch (yapet::InvalidPasswordError& ex) {
79                 assert(pwerror == nullptr);
80                 pwerror = new YACURS::MessageBox3(
81                     _("Invalid Password"), _("Password for file"), _filename,
82                     _("is not correct. Do you want to try again?"),
83                     YACURS::YESNO);
84                 pwerror->show();
85             } catch (std::exception& ex) {
86                 assert(generror == nullptr);
87                 generror = new YACURS::MessageBox2(_("Error"),
88                                                    _("Got following error"),
89                                                    ex.what(), YACURS::OK_ONLY);
90                 generror->show();
91             }
92         } else {
93             // User pressed Cancel
94 
95             YACURS::EventQueue::submit(
96                 YACURS::EventEx<PromptPassword*>(YAPET::EVT_APOPTOSIS, this));
97         }
98 
99         yapet::deleteAndZero(&pwdialog);
100         return;
101     }
102 
103     if (pwerror && evt.data() == pwerror) {
104         if (pwerror->dialog_state() == YACURS::DIALOG_YES) {
105             run();
106         } else {
107             YACURS::EventQueue::submit(
108                 YACURS::EventEx<PromptPassword*>(YAPET::EVT_APOPTOSIS, this));
109         }
110         yapet::deleteAndZero(&pwerror);
111         return;
112     }
113 
114     if (generror && evt.data() == generror) {
115         yapet::deleteAndZero(&generror);
116         YACURS::EventQueue::submit(
117             YACURS::EventEx<PromptPassword*>(YAPET::EVT_APOPTOSIS, this));
118     }
119 }
120 
121 //
122 // Public
123 //
124 
PromptPassword(const std::string & filename)125 PromptPassword::PromptPassword(const std::string& filename)
126     : pwdialog{nullptr},
127       pwerror{nullptr},
128       generror{nullptr},
129       _filename(filename),
130       _cryptoFactory{nullptr} {
131     YACURS::EventQueue::connect_event(
132         YACURS::EventConnectorMethod1<PromptPassword>(
133             YACURS::EVT_WINDOW_CLOSE, this,
134             &PromptPassword::window_close_handler));
135 }
136 
~PromptPassword()137 PromptPassword::~PromptPassword() {
138     if (pwdialog) delete pwdialog;
139     if (pwerror) delete pwerror;
140     if (generror) delete generror;
141 
142     YACURS::EventQueue::disconnect_event(
143         YACURS::EventConnectorMethod1<PromptPassword>(
144             YACURS::EVT_WINDOW_CLOSE, this,
145             &PromptPassword::window_close_handler));
146 }
147 
run()148 void PromptPassword::run() {
149     assert(pwdialog == nullptr);
150     pwdialog = new PasswordDialog(_filename);
151     pwdialog->show();
152 }
153