Annotation of truecrypt/main/textuserinterface.cpp, revision 1.1

1.1     ! root        1: /*
        !             2:  Copyright (c) 2008 TrueCrypt Foundation. All rights reserved.
        !             3: 
        !             4:  Governed by the TrueCrypt License 2.4 the full text of which is contained
        !             5:  in the file License.txt included in TrueCrypt binary and source code
        !             6:  distribution packages.
        !             7: */
        !             8: 
        !             9: #include "System.h"
        !            10: #ifdef TC_UNIX
        !            11: #include <signal.h>
        !            12: #include <termios.h>
        !            13: #include <unistd.h>
        !            14: #endif
        !            15: 
        !            16: #include "Application.h"
        !            17: #include "TextUserInterface.h"
        !            18: 
        !            19: namespace TrueCrypt
        !            20: {
        !            21:        TextUserInterface::TextUserInterface ()
        !            22:        {
        !            23: #ifdef TC_UNIX
        !            24:                signal (SIGHUP, OnSignal);
        !            25:                signal (SIGINT, OnSignal);
        !            26:                signal (SIGQUIT, OnSignal);
        !            27:                signal (SIGTERM, OnSignal);
        !            28: #endif
        !            29: 
        !            30:                FInputStream.reset (new wxFFileInputStream (stdin));
        !            31:                TextInputStream.reset (new wxTextInputStream (*FInputStream));
        !            32:        }
        !            33: 
        !            34:        TextUserInterface::~TextUserInterface ()
        !            35:        {
        !            36: #ifdef TC_UNIX
        !            37:                signal (SIGHUP, SIG_DFL);
        !            38:                signal (SIGINT, SIG_DFL);
        !            39:                signal (SIGQUIT, SIG_DFL);
        !            40:                signal (SIGTERM, SIG_DFL);
        !            41: #endif
        !            42:        }
        !            43: 
        !            44:        shared_ptr <KeyfileList> TextUserInterface::AskKeyfiles (const wxString &message) const
        !            45:        {
        !            46:                wxString msg = _("Enter keyfile");
        !            47:                if (!message.empty())
        !            48:                        msg = message;
        !            49: 
        !            50:                make_shared_auto (KeyfileList, keyfiles);
        !            51: 
        !            52:                wxString s;
        !            53:                wxString m = msg + L" [" + _("none") + L"]: ";
        !            54:                while (!(s = AskString (m)).empty())
        !            55:                {
        !            56:                        keyfiles->push_back (make_shared <Keyfile> (wstring (s)));
        !            57:                        m = msg + L" [" + _("finish") + L"]: ";
        !            58:                }
        !            59: 
        !            60:                return keyfiles;
        !            61:        }
        !            62: 
        !            63:        shared_ptr <VolumePassword> TextUserInterface::AskPassword (const wxString &message, bool verify) const
        !            64:        {
        !            65:                wxString msg = LangString["ENTER_PASSWORD"] + L": ";
        !            66:                if (!message.empty())
        !            67:                        msg = message + L": ";
        !            68: 
        !            69:                SetTerminalEcho (false);
        !            70:                finally_do ({ TextUserInterface::SetTerminalEcho (true); });
        !            71: 
        !            72:                wchar_t passwordBuf[4096];
        !            73:                finally_do_arg (BufferPtr, BufferPtr (reinterpret_cast <byte *> (passwordBuf), sizeof (passwordBuf)), { finally_arg.Erase(); });
        !            74: 
        !            75:                make_shared_auto (VolumePassword, password);
        !            76: 
        !            77:                bool verPhase = false;
        !            78:                while (true)
        !            79:                {
        !            80:                        ShowString (verPhase ? wxString (_("Re-enter password: ")) : msg);
        !            81: 
        !            82:                        const wxString &passwordStr = TextInputStream->ReadLine();
        !            83:                        size_t length = passwordStr.size();
        !            84: 
        !            85:                        ShowString (L"\n");
        !            86: 
        !            87:                        if (length < 1)
        !            88:                        {
        !            89:                                throw_sys_if (ferror (stdin));
        !            90: 
        !            91:                                password->Set (passwordBuf, 0);
        !            92:                                return password;
        !            93:                        }
        !            94: 
        !            95:                        for (size_t i = 0; i < length && i < VolumePassword::MaxSize; ++i)
        !            96:                        {
        !            97:                                passwordBuf[i] = (wchar_t) passwordStr[i];
        !            98:                                const_cast <wchar_t *> (passwordStr.c_str())[i] = L'X';
        !            99:                        }
        !           100: 
        !           101:                        if (verify && verPhase)
        !           102:                        {
        !           103:                                make_shared_auto (VolumePassword, verPassword);
        !           104:                                verPassword->Set (passwordBuf, length);
        !           105: 
        !           106:                                if (*password != *verPassword)
        !           107:                                {
        !           108:                                        ShowInfo (_("Passwords do not match."));
        !           109:                                        verPhase = false;
        !           110:                                        continue;
        !           111:                                }
        !           112:                        }
        !           113: 
        !           114:                        password->Set (passwordBuf, length);
        !           115: 
        !           116:                        if (!verPhase)
        !           117:                        {
        !           118:                                try
        !           119:                                {
        !           120:                                        password->CheckPortability();
        !           121:                                }
        !           122:                                catch (UnportablePassword &e)
        !           123:                                {
        !           124:                                        if (verify)
        !           125:                                        {
        !           126:                                                ShowError (e);
        !           127:                                                verPhase = false;
        !           128:                                                continue;
        !           129:                                        }
        !           130: 
        !           131:                                        ShowWarning ("UNSUPPORTED_CHARS_IN_PWD_RECOM");
        !           132:                                }
        !           133: 
        !           134:                                if (verify)
        !           135:                                {
        !           136:                                        if (password->Size() < VolumePassword::WarningSizeThreshold
        !           137:                                                && !AskYesNo (LangString ["PASSWORD_LENGTH_WARNING"], false, true))
        !           138:                                                continue;
        !           139:                                }
        !           140:                        }
        !           141: 
        !           142:                        if (!verify || verPhase)
        !           143:                                return password;
        !           144: 
        !           145:                        if (!verPhase)
        !           146:                                verPhase = true;
        !           147:                }
        !           148: 
        !           149:                return password;
        !           150:        }
        !           151: 
        !           152:        wstring TextUserInterface::AskString (const wxString &message) const
        !           153:        {
        !           154:                ShowString (message);
        !           155: 
        !           156:                return wstring (TextInputStream->ReadLine());
        !           157:        }
        !           158:        
        !           159:        bool TextUserInterface::AskYesNo (const wxString &message, bool defaultYes, bool warning) const
        !           160:        {
        !           161:                while (true)
        !           162:                {
        !           163:                        wxString s = AskString (StringFormatter (L"{0} (y={1}/n={2}) [{3}]: ",
        !           164:                                message, LangString["YES"], LangString["NO"], LangString[defaultYes ? "YES" : "NO"]));
        !           165: 
        !           166:                        if (s.IsSameAs (L'n', false) || s.IsSameAs (L"no", false) || !defaultYes && s.empty())
        !           167:                                return false;
        !           168: 
        !           169:                        if (s.IsSameAs (L'y', false) || s.IsSameAs (L"yes", false) || defaultYes && s.empty())
        !           170:                                return true;
        !           171:                };
        !           172:        }
        !           173: 
        !           174:        shared_ptr <VolumePath> TextUserInterface::AskVolumePath (const wxString &message) const
        !           175:        {
        !           176:                return make_shared <VolumePath> (AskString (message.empty() ? wxString (_("Enter volume path: ")) : message));
        !           177:        }
        !           178: 
        !           179:        void TextUserInterface::ChangePassword (shared_ptr <VolumePath> volumePath, shared_ptr <VolumePassword> password, shared_ptr <KeyfileList> keyfiles, shared_ptr <VolumePassword> newPassword, shared_ptr <KeyfileList> newKeyfiles) const
        !           180:        {
        !           181:                shared_ptr <Volume> volume;
        !           182: 
        !           183:                // Volume path
        !           184:                if (!volumePath.get())
        !           185:                {
        !           186:                        if (Preferences.NonInteractive)
        !           187:                                throw MissingArgument (SRC_POS);
        !           188: 
        !           189:                        volumePath = AskVolumePath ();
        !           190:                }
        !           191: 
        !           192:                bool passwordInteractive = !password.get();
        !           193:                bool keyfilesInteractive = !keyfiles.get();
        !           194: 
        !           195:                while (true)
        !           196:                {
        !           197:                        // Current password
        !           198:                        if (!passwordInteractive)
        !           199:                        {
        !           200:                                try
        !           201:                                {
        !           202:                                        password->CheckPortability();
        !           203:                                }
        !           204:                                catch (UnportablePassword &)
        !           205:                                {
        !           206:                                        ShowWarning ("UNSUPPORTED_CHARS_IN_PWD_RECOM");
        !           207:                                }
        !           208:                        }
        !           209:                        else if (!Preferences.NonInteractive)
        !           210:                        {
        !           211:                                password = AskPassword ();
        !           212:                        }
        !           213: 
        !           214:                        // Current keyfiles
        !           215:                        try
        !           216:                        {
        !           217:                                if (keyfilesInteractive)
        !           218:                                {
        !           219:                                        // Ask for keyfiles only if required
        !           220:                                        try
        !           221:                                        {
        !           222:                                                keyfiles.reset (new KeyfileList);
        !           223:                                                volume = Core->OpenVolume (volumePath, Preferences.DefaultMountOptions.PreserveTimestamps, password, keyfiles);
        !           224:                                        }
        !           225:                                        catch (PasswordException&)
        !           226:                                        {
        !           227:                                                if (!Preferences.NonInteractive)
        !           228:                                                        keyfiles = AskKeyfiles ();
        !           229:                                        }
        !           230:                                }       
        !           231: 
        !           232:                                if (!volume.get())
        !           233:                                        volume = Core->OpenVolume (volumePath, Preferences.DefaultMountOptions.PreserveTimestamps, password, keyfiles);
        !           234:                        }
        !           235:                        catch (PasswordException &e)
        !           236:                        {
        !           237:                                if (Preferences.NonInteractive || !passwordInteractive || !keyfilesInteractive)
        !           238:                                        throw;
        !           239: 
        !           240:                                ShowInfo (e);
        !           241:                                continue;
        !           242:                        }
        !           243: 
        !           244:                        break;
        !           245:                }
        !           246: 
        !           247:                // New password
        !           248:                if (newPassword.get())
        !           249:                        newPassword->CheckPortability();
        !           250:                else if (!Preferences.NonInteractive)
        !           251:                        newPassword = AskPassword (_("Enter new password"), true);
        !           252: 
        !           253:                // New keyfiles
        !           254:                if (!newKeyfiles.get() && !Preferences.NonInteractive)
        !           255:                {
        !           256:                        if (keyfiles.get() && keyfiles->size() > 0 && AskYesNo (_("Keep current keyfiles?"), true))
        !           257:                                newKeyfiles = keyfiles;
        !           258:                        else
        !           259:                                newKeyfiles = AskKeyfiles (_("Enter new keyfile"));
        !           260:                }
        !           261: 
        !           262:                Core->ChangePassword (volume, newPassword, newKeyfiles);
        !           263: 
        !           264:                ShowInfo ("PASSWORD_CHANGED");
        !           265:        }
        !           266:        
        !           267:        void TextUserInterface::DoShowError (const wxString &message) const
        !           268:        {
        !           269:                wcerr << L"Error: " << static_cast<wstring> (message) << endl;
        !           270:        }
        !           271: 
        !           272:        void TextUserInterface::DoShowInfo (const wxString &message) const
        !           273:        {
        !           274:                wcout << static_cast<wstring> (message) << endl;
        !           275:        }
        !           276: 
        !           277:        void TextUserInterface::DoShowString (const wxString &str) const
        !           278:        {
        !           279:                wcout << str.c_str();
        !           280:        }
        !           281: 
        !           282:        void TextUserInterface::DoShowWarning (const wxString &message) const
        !           283:        {
        !           284:                wcerr << L"Warning: " << static_cast<wstring> (message) << endl;
        !           285:        }
        !           286: 
        !           287:        shared_ptr <GetStringFunctor> TextUserInterface::GetAdminPasswordRequestHandler ()
        !           288:        {
        !           289:                struct AdminPasswordRequestHandler : public GetStringFunctor
        !           290:                {
        !           291:                        AdminPasswordRequestHandler (TextUserInterface *userInterface) : UI (userInterface) { }
        !           292:                        virtual string operator() ()
        !           293:                        {
        !           294:                                UI->ShowString (_("Enter system administrator password: "));
        !           295: 
        !           296:                                TextUserInterface::SetTerminalEcho (false);
        !           297:                                finally_do ({ TextUserInterface::SetTerminalEcho (true); });
        !           298:                                
        !           299:                                string password = StringConverter::ToSingle (wstring (UI->TextInputStream->ReadLine()));
        !           300:                                UI->ShowString (L"\n");
        !           301:                                return password;
        !           302:                        }
        !           303:                        TextUserInterface *UI;
        !           304:                };
        !           305:                
        !           306:                return shared_ptr <GetStringFunctor> (new AdminPasswordRequestHandler (this));
        !           307:        }
        !           308: 
        !           309:        VolumeInfoList TextUserInterface::MountAllDeviceHostedVolumes (MountOptions &options) const
        !           310:        {
        !           311:                while (true)
        !           312:                {
        !           313:                        if (!options.Password)
        !           314:                                options.Password = AskPassword();
        !           315: 
        !           316:                        if (!options.Keyfiles)
        !           317:                                options.Keyfiles = AskKeyfiles();
        !           318: 
        !           319:                        VolumeInfoList mountedVolumes = UserInterface::MountAllDeviceHostedVolumes (options);
        !           320:                        
        !           321:                        if (!mountedVolumes.empty())
        !           322:                                return mountedVolumes;
        !           323: 
        !           324:                        options.Password.reset();
        !           325:                }
        !           326:        }
        !           327:        
        !           328:        shared_ptr <VolumeInfo> TextUserInterface::MountVolume (MountOptions &options) const
        !           329:        {
        !           330:                shared_ptr <VolumeInfo> volume;
        !           331: 
        !           332:                // Volume path
        !           333:                if (!options.Path)
        !           334:                        options.Path = AskVolumePath ();
        !           335:                
        !           336:                if (Core->IsVolumeMounted (*options.Path))
        !           337:                {
        !           338:                        ShowInfo (StringFormatter (LangString["VOLUME_ALREADY_MOUNTED"], wstring (*options.Path)));
        !           339:                        return volume;
        !           340:                }
        !           341: 
        !           342:                // Mount point
        !           343:                if (!options.MountPoint && !options.NoFilesystem)
        !           344:                        options.MountPoint.reset (new DirectoryPath (AskString (_("Enter mount directory [default]: "))));
        !           345:                
        !           346:                VolumePassword password;
        !           347:                KeyfileList keyfiles;
        !           348: 
        !           349:                if ((!options.Password || options.Password->IsEmpty())
        !           350:                        && (!options.Keyfiles || options.Keyfiles->empty())
        !           351:                        && !Core->IsPasswordCacheEmpty())
        !           352:                {
        !           353:                        // Cached password
        !           354:                        try
        !           355:                        {
        !           356:                                volume = UserInterface::MountVolume (options);
        !           357:                        }
        !           358:                        catch (PasswordException&) { }
        !           359:                }
        !           360: 
        !           361:                while (!volume)
        !           362:                {
        !           363:                        // Password
        !           364:                        if (!options.Password)
        !           365:                        {
        !           366:                                options.Password = AskPassword (StringFormatter (_("Enter password for {0}"), wstring (*options.Path)));
        !           367:                        }
        !           368:                        else
        !           369:                        {
        !           370:                                try
        !           371:                                {
        !           372:                                        if (options.Password)
        !           373:                                                options.Password->CheckPortability();
        !           374:                                }
        !           375:                                catch (UnportablePassword &)
        !           376:                                {
        !           377:                                        ShowWarning ("UNSUPPORTED_CHARS_IN_PWD_RECOM");
        !           378:                                }
        !           379:                        }
        !           380: 
        !           381:                        // Keyfiles
        !           382:                        if (!options.Keyfiles)
        !           383:                                options.Keyfiles = AskKeyfiles();
        !           384: 
        !           385:                        // Hidden volume protection
        !           386:                        if (options.Protection == VolumeProtection::None
        !           387:                                && AskYesNo (_("Protect hidden volume?")))
        !           388:                                options.Protection = VolumeProtection::HiddenVolumeReadOnly;
        !           389: 
        !           390:                        if (options.Protection == VolumeProtection::HiddenVolumeReadOnly)
        !           391:                        {
        !           392:                                if (!options.ProtectionPassword)
        !           393:                                        options.ProtectionPassword = AskPassword (_("Enter password for hidden volume"));
        !           394:                                if (!options.ProtectionKeyfiles)
        !           395:                                        options.ProtectionKeyfiles = AskKeyfiles (_("Enter keyfile for hidden volume"));
        !           396:                        }
        !           397: 
        !           398:                        try
        !           399:                        {
        !           400:                                volume = UserInterface::MountVolume (options);
        !           401:                        }
        !           402:                        catch (ProtectionPasswordIncorrect &e)
        !           403:                        {
        !           404:                                ShowInfo (e);
        !           405:                                options.ProtectionPassword.reset();
        !           406:                        }
        !           407:                        catch (PasswordException &e)
        !           408:                        {
        !           409:                                ShowInfo (e);
        !           410:                                options.Password.reset();
        !           411:                        }
        !           412:                }
        !           413: 
        !           414:                return volume;
        !           415:        }
        !           416: 
        !           417:        bool TextUserInterface::OnInit ()
        !           418:        {
        !           419:                try
        !           420:                {
        !           421:                        DefaultMessageOutput = new wxMessageOutputStderr;
        !           422:                        wxMessageOutput::Set (DefaultMessageOutput);
        !           423: 
        !           424:                        InterfaceType = UserInterfaceType::Text;
        !           425:                        Init();
        !           426: 
        !           427:                        SetExitOnFrameDelete (false);
        !           428:                }
        !           429:                catch (exception &e)
        !           430:                {
        !           431:                        ShowError (e);
        !           432:                        return false;
        !           433:                }
        !           434:                return true;
        !           435:        }
        !           436: 
        !           437:        int TextUserInterface::OnRun()
        !           438:        { 
        !           439:                try
        !           440:                {
        !           441:                        if (ProcessCommandLine ())
        !           442:                        {
        !           443:                                Application::SetExitCode (0);
        !           444:                                return 0;
        !           445:                        }
        !           446:                }
        !           447:                catch (exception &e)
        !           448:                {
        !           449:                        ShowError (e);
        !           450:                }
        !           451: 
        !           452:                Application::SetExitCode (1);
        !           453:                return 1;
        !           454:        }
        !           455: 
        !           456:        void TextUserInterface::OnSignal (int signal)
        !           457:        {
        !           458: #ifdef TC_UNIX
        !           459:                try
        !           460:                {
        !           461:                        SetTerminalEcho (true);
        !           462:                }
        !           463:                catch (...) { }
        !           464:                _exit (1);
        !           465: #endif
        !           466:        }
        !           467: 
        !           468:        void TextUserInterface::SetTerminalEcho (bool enable)
        !           469:        {
        !           470: #ifdef TC_UNIX
        !           471:                struct termios termAttr;
        !           472:                if (tcgetattr (0, &termAttr) == 0)
        !           473:                {
        !           474:                        if (!enable)
        !           475:                        {
        !           476:                                termAttr.c_lflag &= ~ECHO;
        !           477:                                throw_sys_if (tcsetattr (0, TCSANOW, &termAttr) != 0);
        !           478:                        }
        !           479:                        else
        !           480:                        {
        !           481:                                termAttr.c_lflag |= ECHO;
        !           482:                                throw_sys_if (tcsetattr (0, TCSANOW, &termAttr) != 0);
        !           483:                        }
        !           484:                }
        !           485: #endif
        !           486:        }
        !           487: 
        !           488:        wxMessageOutput *DefaultMessageOutput;
        !           489: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.