C++ how can I add a linux user to a group programatically - c++

is it possible to add a user on Linux to a group, programatically when I start my program? I am using C++. I know it can be done with the shell, but I need to do it in my C++ program, however I don't know what to use.

You could take 2 approaches:
Use the system() call to execute a shell command to do the work.
Directly modify the /etc/group file. It should be fairly easy to locate the line that contains the group you wish to add to, and then append the user you want to add on the end (making sure to add a comma if there's already a group member).
Given the choice, I'd probably use the first option from the above.
EDIT: As #DevSolar pointed out in his comment, this answer is assuming that your system is using standard local authentication using passwd/shadow/group files in /etc. If your system is NOT using local auth, then that's a completely different ballgame.

Jared Sutton's two options are valid, but I'd like to point out that you don't have to implement editing /etc/group yourself if you use an existing library.
I know of at least busybox, which has implemented this. There's a function defined in libbb/update_passwd.c
int update_passwd(const char *filename, // /etc/group
const char *name, // username
const char *new_passwd, // nullptr
const char *member) // groupname
If you do want to implement it yourself, then you can check out how their function works.

This task is solved by many configuration management software. For example in Salt:
def adduser(name, username):
on_redhat_5 = __grains__.get('os_family') == 'RedHat' and __grains__.get('osmajorrelease') == '5'
if __grains__['kernel'] == 'Linux':
if on_redhat_5:
cmd = 'gpasswd -a {0} {1}'.format(username, name)
else:
cmd = 'gpasswd --add {0} {1}'.format(username, name)
else:
cmd = 'usermod -G {0} {1}'.format(name, username)
retcode = __salt__['cmd.retcode'](cmd, python_shell=False)
return not retcode
As you can see, operating system commands are used. Which one depends on what operating system it is :)

Related

System() function, and calling internet explorer from it, DevC++

I tried making a program that'd take website info, then feed it to system() to start website. I'm aware that characters like (\, ",') don't get fed to the output directly, so I used escape sequences.
I wrote this program, but the command prompt just refuses to go past C:\ path. But if I copy paste the command displayed by my program, internet explorer gets launched. But the case isn't so for my program. Can anybody tell me where is the error?
Here is my code:
#include<iostream>
#include<cstdlib>
using namespace std;
int main()
{
cout<<"Please enter the website you wish to visit: ";
string website,web;
cin>>web;
web= " " + web;
website = "\"%ProgramFiles%\\Internet Explorer\\iexplore\""+web;
cout<<"\n"<<website<<endl<<endl<<endl;
system(website.c_str());
return 0;
}
You are using an environment variable, %ProgramFiles%, in your system command-line; these are specific to the MS-DOS prompt environment, and generally not available in system implementations.
I suggest replacing that with the full path, such as \"C:\Program Files\Internet Explorer\iexplore\", and see if that works.
If that works, then your implementation doesn't implicitly replace environment variables the way a full Command Prompt does, so you will need to query the environment variable separately and construct the path before you run system. See getenv for one possible way (I'm not sure what mingw32 supports, so you may have other options as well).
If that doesn't remedy the problem, I suggest checking if you can launch something simpler, like notepad.exe, to verify that there is nothing interfering with launching an application in general, such as your environment path or permissions.
Pass it in double double quotes:
website = "\"\"%ProgramFiles%\\Internet Explorer\\iexplore\"\""+web;
The system("something") call actually runs the command interpreter cmd in a way similar (but probably not identical) to cmd /c something. This has implications when there are spaces in the command name, see e.g this. I cannot tell exactly why single double quotes work when there's no environment variable involved, and do not work otherwise, but the fact is, double double quotes do work.
If you want to launch the user's preferred browser, consider calling
system("start http://" + websitename);
instead.
Get that environment variable value first.
#include <iostream>
#include <ShlObj.h>
int main() {
char pathToPf[MAX_PATH];
if (S_OK == SHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES, NULL, 0, pathToPf))
std::cout << pathToPf << std::endl;
return 0;
}
See SHGetFolderPath documentation...
Note that I was lazy and using the ASCII version of this function. Use it without the A postfix and deal with the conversation ;)

What does execve() do?

What exactly does execve() do? I've tried looking at the documentation (http://linux.die.net/man/2/execve) but given that I'm very new to linux and this sort of programming it doesn't make a lot of sense. What I want to do is be able to execute this command:
nc -l -p someport -e /bin/sh
Can I do something like the following (where someport is a number such as 4444)
char *command[2];
command[0] = "nc -l -p someport -e /bin/sh"
execve(command[0], name, NULL);
execve asks the operating system to start executing a different program in the current process.
Chances are pretty decent that you want execvp or execlp instead -- you haven't mentioned anything about wanting to provide the environment for the child, but from the looks of things you probably do want the path searched to find the executable you're using.
Correct usage is
extern char * const environ[];
char * const command[] = {"nc", "-l", "-p", "porthere", "-e", "/bin/sh", NULL};
execve("/usr/bin/nc", command, environ);
You must use a full pathname, not a short name such as "nc" (more precisely: no PATH search is done, the pathname must be an actual existing file), and you must split arguments into separate strings beforehand. You also need to propagate the environment somehow, either via the extern environ mentioned in the above snippet or as obtained from the third parameter of main(); the latter is slightly more standards-blessed but may be more painful to pass around as needed.

C++: How to escape user input for safe system calls?

On a Linux platform, I have C++ code that goes like this:
// ...
std::string myDir;
myDir = argv[1]; // myDir is initialized using user input from the command line.
std::string command;
command = "mkdir " + myDir;
if (system(command.c_str()) != 0) {
return 1;
}
// continue....
Is passing user input to a system() call safe at all?
Should the user input be escaped / sanitized?
How?
How could the above code be exploited for malicious purposes?
Thanks.
Just don't use system. Prefer execl.
execl ("/bin/mkdir", "mkdir", myDir, (char *)0);
That way, myDir is always passed as a single argument to mkdir, and the shell isn't involved. Note that you need to fork if you use this method.
But if this is not just an example, you should use the mkdir C function:
mkdir(myDir, someMode);
Using system() call with command line parameters without sanitizing the input can be highly insecure.
The potential security threat could be a user passing the following as directory name
somedir ; rm -rf /
To prevent this , use a mixture of the following
use getopt to ensure your input is
sanitized
sanitize the input
use execl instead of system to execute
the command
The best option would be to use all three
Further to Matthew's answer, don't spawn a shell process unless you absolutely need it. If you use a fork/execl combination, individual parameters will never be parsed so don't need to be escaped. Beware of null characters however which will still prematurely terminate the parameter (this is not a security problem in some cases).
I assume mkdir is just an example, as mkdir can trivially be called from C++ much more easily than these subprocess suggestions.
Reviving this ancient question as I ran into the same problem and the top answers, based on fork() + execl(), weren't working for me. (They create a separate process, whereas I wanted to use async to launch the command in a thread and have the system call stay in-process to share state more easily.) So I'll give an alternative solution.
It's not usually safe to pass user input as-is, especially if the utility is designed to be sudo'd; in order to sanitize it, instead of composing the string to be executed yourself, use environment variables, which the shell has built-in escape mechanisms for.
For your example:
// ...
std::string myDir;
myDir = argv[1]; // myDir is initialized using user input from the command line.
setenv("MY_DIR", myDir, 1);
if (system("mkdir \"${MY_DIR}\"") != 0) {
return 1;
}
// continue....

Can two windows apps communicate using the command-line?

I worked on a Unix app where two applicants ran and talked to each other using the command-line, i.e each had a loop something like (treat this as pseudo code):
bool stop=false;
do
{
stringstring cmdBuffer;
cin >> cmdBuffer
string ret = processCommand(cmdBuffer);
if(ret.length()==0)
stop=true;
else
cout << ret;
}
while(!stop);
Is there any reason two Windows apps can't do the same? Would they have to be running on the same 'command prompt' or be console apps, or does the notion of command-lines go beyond being able to see a command prompt in front of me?
For reference, in my case one app would be running the other, they're not two separate apps run up independently.
I'd say redirect the input and output handles(SetStdHandle), but using a named pipe is safer and more secure, plus you can use sync functions on it.
you can also use a global mutex/event or Mapped memory instead, as both are globally named and easy to get/set and read/write to.

How to programmatically gain root privileges?

I am writing some software (in C++, for Linux/Mac OSX) which runs as a non-privileged user but needs root privileges at some point (to create a new virtual device).
Running this program as root is not a option (mainly for security issues) and I need to know the identity (uid) of the "real" user.
Is there a way to mimic the "sudo" command behavior (ask for user password) to temporarily gain root privileges and perform the particular task ? If so, which functions would I use ?
Thank you very much for your help !
If you need root privileges every time, the best thing is to start your program as root and drop them (in a subprocess) with setuid and setgid. That's what apache does when it needs to bind to the restricted port 80.
If gaining root rights is the exception instead of the rule and the program is run interactively, another way is to write a program add_interface and execute
sudo add_interface args
and let sudo handle authentication for you. Instead of sudo, you may want to use a graphical frontend like gksu, gksudo, kdesu, or kdesudo. I wouldn't try to implement secure password input myself; it can be a tricky problem and you'll probably leave gaping security holes and functionality problems (Do you support fingerprint readers?).
Another alternative is polkit, previously called PolicyKit.
Original answer
You might consider the setuid switch on the executable itself. Wikipedia has an article on it which even shows you the difference between geteuid() and getuid() quite effectively, the former being for finding out who you're "emulating" and the latter for who you "are". The sudo process, for example, geteuid should return 0 (root) and getuid your user's id, however, its sub-processes do truly run as root (you can verify this with sudo id -u -r).
I don't think there's a way to easily programmatically gain root access - after all, applying the principle of least privilege, why would you need to? Common practise is to run only limited parts of code with elevated privileges. A lot of daemons etc are also set up under modern systems to run as their own user with most of the privileges they need. It's only for very specific operations (mounting etc) that root privileges are truly needed.
2013 update
My original answer stands (although my 2013 self might make a better job of it than my 2010 one), but if you are designing an application that requires root access, you may want to consider exactly what sort of root access is needed and consider the use of POSIX Capabilities (man page). These are different to capability-based security as implemented in L4 et al. POSIX capabilities allow your application to be granted a subset of root's powers. For example CAP_SYS_MODULE will allow you to insert kernel modules, but give you no other root powers. This is in use in distributions e.g. Fedora has a feature to completely remove setuid binaries with indiscriminate root access.
This matters because as a programmer, your code is obviously perfect! But, the libraries on which you depend (sigh, if only you'd written them!) might have vulnerabilities in them. Using capabilities, you can limit the use of this exploit, and save yourself and your company from security-related scrutiny. This makes everyone happier.
You can't gain root privileges, you must start out with them and reduce your privileges as needed. The usual way that you do this is to install the program with the "setuid" bit set: this runs the program with the effective userid of the file owner. If you run ls -l on sudo, you'll see that it is installed that way:
-rwsr-xr-x 2 root root 123504 2010-02-25 18:22 /usr/bin/sudo
While your program is running with root privileges, you can call the setuid(2) system call to change your effective userid to some non-privileged user. I believe (but haven't tried this) that you could install your program as root with the setuid bit on, immediately reduce privilege, and then restore privilege as needed (it's possible, however, that once you lower your privilege you won't be able to restore it).
A better solution is to break out the piece of your program that needs to run as root, and install it with the setuid bit turned on. You will, of course, need to take reasonable precautions that it can't be invoked outside of your master program.
Normally this is done by making your binary suid-root.
One way of managing this so that attacks against your program are hard is to minimize the code that runs as root like so:
int privileged_server(int argc, char **argv);
int unprivileged_client(int argc, char **argv, int comlink);
int main(int argc, char **argv) {
int sockets[2];
pid_t child;
socketpair(AF_INET, SOCK_STREAM, 0); /* or is it AF_UNIX? */
child = fork();
if (child < 0) {
perror("fork");
exit(3);
} elseif (child == 0) {
close(sockets[0]);
dup2(sockets[1], 0);
close(sockets[1]);
dup2(0, 1);
dup2(0, 2); /* or not */
_exit(privileged_server(argc, argv));
} else {
close(sockets[1]);
int rtn;
setuid(getuid());
rtn = unprivileged_client(argc, argv, sockets[0]);
wait(child);
return rtn;
}
}
Now the unprivileged code talks to the privileged code via the fd comlink (which is a connected socket). The corresponding privileged code uses stdin/stdout as its end of the comlink.
The privileged code needs to verify the security of every operation it needs to do but as this code is small compared to the unprivileged code this should be reasonably easy.
You might want to take a look at these APIs:
setuid, seteuid, setgid, setegid, ...
They're defined in the header <unistd.h> in Linux systems (don't know much about MAC, but you should have a similar header there too).
One problem that I can see is that the process must have sufficient privileges to change its user-/group- IDs. Otherwise calls to the above functions will result in an error with errorno set to EPERM.
I would suggest that you run your program as the root user, change effective user ID (using seteuid) to an underprivileged user at the very beginning. Then, whenever you need to elevate permissions, prompt for a password then use seteuid again to revert to the root user.
On OS X, you can use the AuthorizationExecuteWithPrivileges function. The page on Authorization Services Tasks has some elaborate discussion of this (and related) functions.
Here's a bit of C++ code to execute a program with administrator privileges:
static bool execute(const std::string &program, const std::vector<std::string> &arguments)
{
AuthorizationRef ref;
if (AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &ref) != errAuthorizationSuccess) {
return false;
}
AuthorizationItem item = {
kAuthorizationRightExecute, 0, 0, 0
};
AuthorizationRights rights = { 1, &item };
const AuthorizationFlags flags = kAuthorizationFlagDefaults
| kAuthorizationFlagInteractionAllowed
| kAuthorizationFlagPreAuthorize
| kAuthorizationFlagExtendRights;
if (AuthorizationCopyRights(ref, &rights, kAuthorizationEmptyEnvironment, flags, 0) != errAuthorizationSuccess) {
AuthorizationFree(ref, kAuthorizationFlagDestroyRights);
return false;
}
std::vector<char*> args;
for (std::vector<std::string>::const_iterator it = arguments.begin(); it != arguments.end(); ++it) {
args.push_back(it->c_str());
}
args.push_back(0);
OSStatus status = AuthorizationExecuteWithPrivileges(ref, program.c_str(), kAuthorizationFlagDefaults, &args[0], 0);
AuthorizationFree(ref, kAuthorizationFlagDestroyRights);
return status == errAuthorizationSuccess;
}
You can try launching the command to create the virtual device (including sudo) through a background shell. Ask for the users password in a dialog of your own and pipe that into the shell when sudo asks for it. There are other solutions like using gksu, but those are not guaranteed to be available on every machine.
You don't run your entire program as root, but only the small part of it that needs root. You should spawn a separate process for that and sudo may be of assistance to you.