Password Manager - Continuing / Long-Term Things - c++

Okay, I know very well how everybody feels about homemade password managers, but I would like help with mine. Not for actual use, just for the sake of learning.
I was wondering, in C++ how to have long-term variables. Or really, have anything long-term.
What do I mean by long-term? Something that is saved or continues upon next run of the .exe. In my case, I want where, the first time you run the program it asks you to enter an access password, so next time you launch the program, you will have to type the password chosen when you first launched.
Currently, I just use an if() statement to check if password is equal to my desired password, and if it is, to run. However, that is far from actually effective and isn't very practical.
Something I thought of was to create a text file somewhere containing the access password, and read it, but that kind of defeats the purpose of a password manager.

Every variable in your program is only in memory and lost at exit. You must store it on your disk and later read it from there.
There are many ways to do that directly or indirectly.
A very simple low level way is to use ofstream and ifstream. E.g.:
#include <iostream>
#include <fstream>
int main() {
using namespace std;
int counter = 0;
// try to load counter from file
{
ifstream myfile("mycounter.txt");
if (myfile.is_open())
{
myfile >> counter;
}
myfile.close();
}
cout << "current counter: " << counter << endl;
// save counter to file
{
ofstream myfile;
myfile.open("mycounter.txt");
myfile << counter << endl;
}
}
You might be more comfortable with the C-functions fopen, fread, fwrite, fclose, etc.
Then, there are databases and there are easy libraries to use such databases. Check out sqlite, you can use it from C++.

You could start a database or save/write the data into files.

Related

c++ password storage .txt file + masking input

I'm pretty new to programming - just starting out with C++. So I wanted to make an application - just for fun - which would mask user input with asterisks. I did some research and found exactly what I was looking for. As you can see inside the code below it works fine but only checks password from a char I put - "correct_password". I thought it'd be more challenging to extend options. The program would write two options out: 1. register - just put your login and password (without asterisks), then store it into a file (fstream I guess), 2. login - after putting login and password (with asterisks just the way it is in getpass) it would check the file for data if user is actually registered. Even thought maybe about encrypting data in that file, although I have no idea how to proceed. Well, it's just made up thing to learn some new stuff, I know it's not really a THING and there's no really a purpose to write such code - just messing around with C++. Maybe you got some ideas how to snap that? After I wrote this asterisk thing i don't really see where I should put those other options, storing in file and so on. Would love to go through some ideas and appreciate the input from more experienced coders :)
I tried using fstream inside getpass but didn't work out. Generally I'd like to extend this program with login and password input, storing them into .txt file and then program would check if user is registered and while logging with this data input would be masked with asterisks - just like my first idea of that program which is only masking password input. I don't really know how to split unmasked input with that inside getpass.
#include <iostream>
#include <string>
#include <windows.h>
using namespace std;
string getpass(const char *dat, bool s_asterisk=true)
{
const char BACKSPACE=8;
const char RETURN=13;
string password;
unsigned char ch=0;
cout << dat;
DWORD con_mode;
DWORD dwRead;
HANDLE hIn=GetStdHandle(STD_INPUT_HANDLE);
GetConsoleMode( hIn, &con_mode );
SetConsoleMode( hIn, con_mode & ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT) );
while(ReadConsoleA( hIn, &ch, 1, &dwRead, NULL) && ch !=RETURN)
{
if(ch==BACKSPACE)
{
if(password.length()!=0)
{
if(s_asterisk)
cout <<"\b \b";
password.resize(password.length()-1);
}
}
else
{
password+=ch;
if(s_asterisk)
cout <<'*';
}
}
cout << endl;
return password;
}
int main()
{
const char *correct_password="fdsidfjsijdsf21128321873";
START:
string password=getpass("Enter the password: ",true);
if(password==correct_password){
cout <<"\nCorrect password."<<endl;
exit(1);
}else{
cout <<"\nIncorrect password. Try again.\n"<<endl;
goto START;
}
return 0;
}
Usually you don't want to store actual passwords in a file. Although encrypting them would help security (to at least some degree), it's still generally pretty insecure and better avoided.
What you usually want to do instead is salt the password, then hash the salted password with a cryptographic hash. Then you store the salt and the hash, rather than the password itself.
Then (for the simplest case) when the user wants to log in, you repeat the same process: retrieve the salt for their password, apply the salt to the password they enter, hash the result, and finally compare that result to the value you stored. If they match, you assume the user entered the correct password. If they don't match, you know they didn't.
Note that this is only reasonable for the user logging into your application locally (or at least over a secure connection). If they might log in over an insecure connection, you need to get considerably more sophisticated still.
Another major point though: nearly all of this should happen outside getpass. getpass should do exactly one thing: read in a password from the user. Salting, hashing, storing, and so on, should all happen separately from that.

How to make a C++ program that works with a .txt file without showing it

My program needs to use a hidden text file to keep track of user's name.
But when the program starts, if it can't find the 'Name.txt' file in the same directory, it generates one that is visible to the user.
The user can view it, edit it, and so on. How can I prevent this from happening, so that only my program can modify the file?
Also, is there a better way to keep knowledge of the name of the user (keep in mind I'm new to programming in general, not only to C++)?
#include "stdafx.h"
#include <fstream>
#include <iostream>
#include <string>
#include <Windows.h>
using std::string;
using std::cout;
using std::cin;
using std::ifstream;
using std::ofstream;
int main()
{
string line;
ifstream example;
example.open("Name.txt");
getline(example, line);
if (line.compare("") == 0)
{
example.close();
string con;
cout << "Welcome to this program!\n";
cout << "Do you want to register? (y/n) ";
cin >> con;
con[0] = tolower(con[0]);
if (con.compare("n") != 0)
{
string name;
ofstream one;
one.open("Name.txt");
cout << "What's your name? ";
cin >> name;
one << name;
one.close();
cout << "See you later " << name << ".";
Sleep(4000);
}
}
else
{
cout << "Welcome back " << line << ".";
example.close();
Sleep(4000);
}
}
EDIT : I just realised I said 'to keep track of the user'. Now I realized why you guys thought I wanted to do something bad with this program. I corrected it now, what I meant was 'to keep track of the user’s name'.
I understand that you want to maintain a file that contains the names of all the registered users, or some other kind of current-user-independent data.
The problem
Your code tries to open the file in the current working directory of the program. Unfortunately, it depends on the way the user has launched your program.
It also ignores possible errors during the opening when reading the file. So if the file isn't there, your code will open the file as ofstream for writing (which will create the file if it doesn't exist).
How to solve it ?
To fulfill your requirements, you should open the file in a predetermined location (for example fixed during the installation process, or in the program's configuration). See this article, on where to ideally store data and configuration files on windows platform.
If you want to make sure that the program only opens the file if it already exists, you should verify the result of the open on the ifstream and issue an error message if this failed:
example.open("Name.txt");
if (!example) {
cout << "OUCH ! Fatal error: the registration file couldn't be opened !" <<endl;
exit (1);
}
How to protect the file against users ?
Note however that if your program reads and writes data from the file, the user could find it also and edit it manually. This will be difficult to prevent.
Alternatively you could consider using the windows registry, which is less trivial for the user to edit (although not impossible). The major inconvenience of this approach is that it's system dependent and it will make the porting of your code to other platforms much more difficult.
If you want to fully protect your file, you could as suggested by Chris in the comment, encrypt the file. Encryption is complex business; Consider using a library such as openssl or a proven algorithm.
This will protect you against ordinary users. But you'd still be exposed to hackers able to reverse engineer your code and to find the encryption key that must be somehow embedded in your code to decrypt the file.

C++ - ofstream doesn't output to file until I close the program

I have the following code:
ofstream mOutFile.open(logPath, ios_base::app);
string lBuilder;
lBuilder.append("========================================================\n");
lBuilder.append("Date: ");
lBuilder.append(asctime(timeinfo));
lBuilder.append("\n");
lBuilder.append("Log Message:\n");
lBuilder.append(toLog);
lBuilder.append("\n");
lBuilder.append("========================================================\n\n");
int lSize = lBuilder.size();
char* lBuffer = new char[lSize];
int index = 0;
for each (char c in lBuilder)
lBuffer[index++] = c;
mOutFile.write(lBuffer, lSize);
mOutFile.flush();
Unfortunately, until I close the app (I assume that closing the ofstream would work as well) the output does not get written to the text file. I know I could probably close and reopen the stream and everything will "just work" but that seems like a silly and incorrect solution. What am I doing wrong here?
I have also tried the following variations based on other questions I have found here, but these solutions did not work:
mOutputFile << flush;
mOutputFile << endl;
Thanks in advance for any assistance on this.
edit Everything in this code is working visual c++, it builds and works fine except the file is not written to until the stream is closed, even if I force a flush. Also, I switched from using the << operator to the char * and .write () to see if anything behaved differently.
std::ofstream file(logPath, ios_base::app);
file << "========================================================\n"
<< "Date: " << asctime(timeinfo)
<< "\nLog Message:\n" << toLog
<< "\n========================================================\n\n"
<< std::flush;
//if you want to force it write to the file it will also flush when the the file object is destroyed
//file will close itself
This is not only easier to read but it will probably also be faster than your method + it is a more standard appraoch
I ended up just "making it work" by closing and reopening the stream after the write operation.
mOutputFile << "all of my text" << endl;
mOutputFile.close();
mOutputFile.open(mLogPath);
EDIT After trying out forcing the flush on a few other systems, it looks like something just isn't performing correctly on my development machine. Not good news but at least the above solution seems to work when programmatically flushing the ofstream fails. I am not sure of the implications of the above code though, so if anyone wants to chime in if there are implications of closing and reopening the stream like this.
You can perform the following steps to validate some assumptions:
1.) After flush(), the changes to the file should be visible to your application. Open the file as std::fstream instead of std::ofstream. After flushing, reset the file pointer to the beginning and read the contents of the file. Your newly written record should be there. If not, you probably have a memory corruption somewhere in your code.
2.) Open the same file in an std::ifstream after your call to flush(). Then read the contents of the file. Your newly written record should be there. If not, then there's probably another process interfering with your file.
If both works, then you may want to read up on "file locking" and "inter-process syncronization". The OS can (theoretically) take as much time as it wants to make file changes visible to other processes.

How to search in a file the best, easiest way?

Can somebody tell me if this is a good way to search an account by an id, and to output all data about him? If not, which is the best way?
I have this:
void account::showacc() {
ifstream inFile;
inFile.open("account.dat",ios::binary|ios::in|ios::app);
int accnum1,n;
cout<<"Enter account num: ";
cin>>accnum1;
n=test();
for(int i=0;i<n;i++)
{
inFile.read((char*)&acc,sizeof(acc));
if(accnum==accnum1)
{
cout<<"account number is: "<<accnum<<endl;
cout<<"The possesor's name is :"<<name;
}
}
inFile.close();
}
And the test() is:
int account::test()
{
ifstream inFile;
inFile.open("account.dat",ios::binary|ios::in|ios::app);
inFile.seekg(0,ios::end);
int n;
n=inFile.tellg()/sizeof(acc);
inFile.close();
return n;
}
Well, this would work, but it's going to be slow ... depending on how big your file is, and how long your program runs (i.e., if it's a persistent program running in the background or a service of some type), it would be a much better idea to memory-map the file, and/or read the entire file into a std::stringstream, and then scan the stored file in memory. Again, this will all depend on how big your file is, and how persistent the reading program is. If it's a huge file, and your program is only run once and then quit, then yes, your current method is okay.
You could make it much more efficient by changing the for loop. As it is, it looks like you go through the entire file, even if you find the account number. Assuming that there are no duplicate numbers, you should set it up to terminate if it finds the the number.
Depending on your use case, you might be better off using a database engine such as sqlite and let it take care of the searching for you. Sqlite exists as a C++ library that you can use in your program.

Checking for file existence in C++

Currently I use something like:
#include <sys/stat.h>
#include "My_Class.h"
void My_Class::my_function(void)
{
std::ofstream my_file;
struct stat file_info;
if ( filename_str.compare("")!=0 &&
stat(filename_str.c_str(),&file_info) == 0 )
{
my_file.open(filename_str.data(),std::ios::trunc);
//do stuff
my_file.close();
}
else if ( filename_str.compare("")==0 )
{
std::cout << "ERROR! ... output filename not assigned!" << std::endl;
}
else
{
std::cout << "ERROR! File :" << std::endl
<< filename_str << std::endl
<< "does not exist!!" << std::endl;
}
}
...is this a decent way to go, or is there a better alternative? Seems like I could run amuck of permissions if I don't have permissions to read the file.
This is NOT a homework, question, it is a question about best practice.
I'd use the boost::filesystem constructs. Not only are they cross platform, they're part of the next standard library.
Generally I think it is best to just try opening it and catch an error.
IMO, checking permissions is unwise because what if it's a Linux box and you check its attributes, decide you can't write to it, but the filesystem supports ACL's and they do grant you permission? (As a sysadmin I can't stand when apps do this. I like ACL's and if you're an app, don't tell me you can't write to a file unless you've tried first.)
Conceptually, I'd say it depends on what you're planning to do with that file..
If you need its contents, go ahead and try to open it, and be prepared to handle failure gracefully, for the reasons Ken detailed.
If you are not currently interested in its contents (for example, when enumerating directory contents, or only planning to access a file at some point in the future, etc.), you might be better off just checking attributes for now. Otherwise, nasty things like hierarchical storage management may trigger an expensive (=slow) recall of file contents from, say, a tape backup or network (whereas attributes may have been cached). You could try to avoid that by checking for respective file attributes, but that's additional complexity, too.
So as a best practice, I'd suggest to open files sparingly (i.e., if you're not immediately interested in the contents, contend yourself with file attribute-based information), AND handle failure strictly in response to the actual call that opens the file when you need it.