Get logged in user in Ubuntu 16.04 LTS Desktop - c

I'm working on a C application in which I need the name of the currently logged in user. I have tried using getlogin() and getlogin_r() with no success (tested on multiple systems with Ubuntu 16.04 LTS). The application will run as root so I cannot use the environment variables.
Both getlogin() and getlogin_r() work just fine on other Ubuntu 17.04/17.10/18.04(beta) so I don't understand why it doesn't work in 16.04.
Here is a code snippet that I used to test:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
int main(int argc, char *argv[])
{
char user[512] = {0};
int ret = getlogin_r(user, 512);
if ( ret != 0){
fprintf(stderr, "Unable to get User name. Return: %d\n", ret);
}
else{
fprintf(stdout, "Username: %s\n", user);
}
char *lgn;
struct passwd *pw;
if ((lgn = getlogin()) == NULL || (pw = getpwnam(lgn)) == NULL)
{
fprintf(stderr, "Get of user information failed.\n");
}
struct passwd *pwd = getpwuid(getuid());
if (pwd){
fprintf(stdout, "Success! Username: %s\n", pwd->pw_name);
}else
fprintf(stderr, "Failed");
return 0;
}
This is the output generated when I execute the code as root:
Unable to get User name. Return : 2
Get of user information failed.
Success! Username: root
getpwuid returns the details of the user running the process so it is not helpful.
I'm kind of stuck now and any help is highly appreciated.
Output using strerror()
getlogin_r() : No such process
getlogin() : No such file or directory
Success! Username: root

Related

How can I fork&exec bash shell in C?

Trying to create a new bash shell in C and bring it to the user, this is my code:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
char* secretpass = "password";
char password[50];
printf("%s", "Password: ");
fgets(password, 50, stdin);
password[strcspn(password, "\n")] = 0;
if (!strcmp(password, secretpass)){
pid_t pid = fork();
if (pid == 0){
execl("/bin/bash", "bash", NULL);
}
}
return 0;
}
After running the code (ELF), i get a new bash shell in ps but it's not my shell because echo $$ brings the first shell, what can I do to get the new shell to screen? kernel module will help?
EDIT:
edited my code for more help, /dev/chardev is a char device that come up with the boot process, the driver is also 0666 (.rw.rw.rw.) writable for everyone, the system(cmd) says at there is no permission at console, even if I do the command myself after execve.
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <pwd.h>
#define MAX 50
#define USERNAME 2
int main(int argc, char const *argv[])
{
// Declare variables.
const char* username = argv[USERNAME];
char* password = (char*)calloc(MAX, sizeof(char));
char* cmd = (char*)calloc(5 * MAX, sizeof(char));
char* secretpass = "password";
printf("%s", "Password: ");
fgets(password, MAX, stdin);
password[strcspn(password, "\n")] = 0;
if (!strcmp(password, secretpass)){
int err;
struct passwd* pw_user = getpwnam(username);
//printf("-%s-%s-%d-%d-%s-%s-%s-\n", pw_user->pw_name, pw_user->pw_passwd,
//pw_user->pw_uid, pw_user->pw_gid, pw_user->pw_gecos,
//pw_user->pw_dir, pw_user->pw_shell);
if ( (err = fchown(0, pw_user->pw_uid, pw_user->pw_gid) ) != 0)
printf("%s %d\n", "fchown error", err);
if ( (err = setpgid(0, 0) ) != 0)
printf("%s %d\n", "setpgid error", err);
if ( (err = tcsetpgrp(0, getpid()) ) != 0)
printf("%s %d\n", "tcsetpgrp error", err);
if ( (err = chdir(pw_user->pw_dir) ) != 0)
printf("%s %d\n", "chdir error", err);
if ( (err = setgid(pw_user->pw_gid) ) != 0)
printf("%s %d\n", "setgid error", err);
if ( (err = setuid(pw_user->pw_uid) ) != 0)
printf("%s %d\n", "setuid error", err);
sprintf(cmd, "%s \"%d %d %d\" %s", "echo", pw_user->pw_uid, pw_user->pw_gid, getpid(), "> /dev/chardev");
system(cmd);
const char *args[] = {"bash", "--rcfile", "/etc/bashrc", NULL};
char LOGNAME[MAX];
char HOME[MAX];
char USER[MAX];
sprintf(LOGNAME, "%s%s", "LOGNAME=", pw_user->pw_name);
sprintf(HOME, "%s%s", "HOME=",pw_user->pw_dir);
sprintf(USER, "%s%s", "USER=", pw_user->pw_name);
const char *env[] = {"SHELL=/bin/bash", LOGNAME, HOME, USER, "IFS= ","PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin", "TTY=tty1", NULL}; /* need to generate these; TTY is passed to you */
execve("/bin/bash", args, env);
}
else
execl("/bin/login", "login", NULL);
return 0;
}
always setpgid error and if username isn't root there are also setuid and chdir errors.
From the comments: you're trying to write a login program.
Ok. That's a bit more, and you're going about this all the wrong way. We don't want to fork at all. Let init worry about waiting. Anyway, we get to write a long sequence here:
int targetuid = ... ; /* You need a strategy for getting this */
int targetgid = ... ; /* You need a strategy for getting this */
const char *homdir = ... ; /* You need a strategy for getting this */
if (!strcmp(password, secretpass)){
/* Start up the user's shell */
fchown(0, targetuid, targetgid);
setpgid(0, 0);
tcsetpgrp(0, getpid());
chdir(homedir);
setgid(targetgid);
setuid(targetuid);
const char *args[] = {"-bash", NULL};
const char *env[] = {"SHELL=/bin/bash", "LOGNAME=...", "HOME=...", "USER=...", IFS="...", PATH=/bin:/usr/bin", "TERM=...", NULL }; /* need to generate these; TERM is passed to you */
execve("/bin/bash", args, env);
}
This is very much involved and I actually don't recommend this unless you really have to. I learned a ton when I tried this but it took forever to get it working right.
Particular subpoints: 1) The tty device needs to be owned by the user after a successful login. Thus the fchown(0, ...) call to give ownership to the user. 2) The chdir() first is traditional; you could reverse the order if you wanted to but I don't see why. 3) Starting the shell with a leading - in argv0 tells the shell that it's a login shell. Check in ps -f and you can see this.
I picked up your new code; it actually looks pretty good. The only mistake I can spot is my own; the variable is TERM not TTY (now corrected in my sample above) and the best place to get its value is getenv(). On running your code I only had to make only one correction; that is putting the -bash back. The only error it spits out is the one about chardev; what is chardev?
I guess your failures aren't in this code at all but rather in your kernel.
Info from chat: OP has a custom kernel with a custom /dev/chardev; I can't explain the failures as the code works for me. There may or may not be other changes to the kernel.

C:Program works fine but with gdb it crashes

I'm new in C and have some problem. Here is my code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
int read_password(FILE *file, char *password, size_t n) {
fgets(password, n, file);
password[strcspn(password, "\n")] = '\0';
}
void elevated_shell(){
gid_t gid = getegid();
setresgid(gid,gid,gid);
fflush(stdout);
system("/bin/bash");
}
void regular_shell(){
gid_t gid = getgid();
setresgid(gid,gid,gid);
fflush(stdout);
system("/bin/bash");
}
int main(int argc, char **argv){
char flag[100];
char password[100];
FILE *file;
printf("Hi! Welcome to my secure shell software!\n");
// Read in the root password
file = fopen("flag.txt", "r");
if(file == NULL) {
printf("FAIL: Failed to open the password file\n");
return -3;
} else {
read_password(file, flag, sizeof(flag));
}
// Read in the user's password
printf("Please enter the password: ");
fflush(stdout);
read_password(stdin, password, sizeof(password));
if(strcmp(flag,password) == 0) {
printf("Correct! Here's an elevated shell :)\n");
elevated_shell();
} else {
printf("Incorrect! No elevated shell for you >:)\n");
regular_shell();
}
}
So, I've compiled this file and run. It works fine when I run it directly but whenever I try to examine memory with gdb it crashes. For example when breakpoint is set at main function and run program is run fopen function returns Null because program print out
FAIL: Failed to open the password file and quits. Hope you can help.
GDB uses the user privileges that runs the program (type whoami to get noticed) not by privileges that the program has.

How to do double authentication using libssh module?

My SSH server uses double authtication. I do not know how its implemented. But initially its asks for a password, then again asks for another password to login to a separate console which is different from usual control.
My code is similar to the example code shown in the documentations,
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <libssh/libssh.h>
int main(int argc, char * argv[])
{
ssh_session my_ssh_session = ssh_new();
int rc;
char * password;
char * username = "admin";
// Check if ssh session exists.
if(my_ssh_session == NULL)
{
exit(-1);
}
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "x.x.x.x");
rc = ssh_connect(my_ssh_session);
if (rc != SSH_OK)
{
fprintf(stderr, "Error Connecting to Server: %s.\n", ssh_get_error(my_ssh_session));
exit(-1);
}
password = getpass("Password: ");
rc = ssh_userauth_password(my_ssh_session, username, password);
if (rc != SSH_AUTH_SUCCESS)
{
fprintf(stderr, "ERROR Authenticating: %s.\n", ssh_get_error(my_ssh_session));
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
}
else
{
printf("Authentication Successful.\n");
}
ssh_free(my_ssh_session);
}
How do i implement a double authtication in this ? can you kindly help me out ?
What version of
libssh do you have?
"versions 0.5.1 and above have a logical error in the handling of a SSH_MSG_NEWKEYS and SSH_MSG_KEXDH_REPLY package. A detected error did not set the session into the error state correctly and further processed the packet which leads to a null pointer dereference. This is the packet after the initial key exchange and doesn’t require authentication."
Ref libssh

can't generate core file after change user from root to nobody in c language

after change user from root to nobody in c language, and I am sure the program core dump, but always can't generate core file.
I'm sure nobody have the right to generate file in current dir. and ulimit -c is unlimited, and I use :
system("echo 'tesstestestestestetestestet!!!!!!' > hahahahhaahahah");
after change user from root to nobody, the file hahahahhaahahah was created!
so, I'm very confuse!
here is my c file:
#include <pwd.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
int main()
{
#if 1
struct passwd *pw;
//char *username = "root";
char *username = "nobody";
if (getuid() == 0 || geteuid() == 0)
{
if (username == 0 || *username == '\0')
{
fprintf(stderr, "can't run as root without the -u switch\n");
exit(-1);
}
if ((pw = getpwnam(username)) == NULL)
{
fprintf(stderr, "can't find the user %s to switch to\n", username);
exit(-1);
}
if (setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0)
{
fprintf(stderr, "failed to assume identity of user %s\n", username);
exit(-1);
}
}
#endif
printf("now user change to group id %d, user id %d\n", getgid(), getuid());
system("echo 'tesstestestestestetestestet!!!!!!' > hahahahhaahahah");
char *test_a = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
char *test_b;
strcpy(test_b, test_a);
*(char *)1=1;
printf("test_b:%s\n", test_b);
}
Read carefully core(5) man page:
There are various circumstances in which a core dump file is not produced:
.... skipping some text from the man page ....
The process is executing a set-user-ID (set-group-ID) program that is owned by a user (group) other than the real user (group) ID of the process.
So basically, after a successful setuid(2) syscall, core is not dumped.(for security reasons)
See also the Linux specific prctl(2) syscall, with PR_SET_DUMPABLE.
Read also http://advancedlinuxprogramming.com/
NB. Have a nobody writable directory is probably a bad idea. The nobody user should usually not own any file or directory!

Checking username: getpwnam / getpwnam_r: No such file or directory

I'm trying to make a web logging and I use getpwnam() function to check username existing. But for valid username getpwnam returns error: No such file or directory. So I tried getpwnam_r(), but it also failed with the same error. I'm running on embedded arm linux and I use /etc/passwd for password storing (I don't have /etc/shadow). My test program is:
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int
main(int argc, char *argv[])
{
struct passwd pwd;
struct passwd *result;
char *buf;
size_t bufsize;
int s;
if (argc != 2) {
fprintf(stderr, "Usage: %s username\n", argv[0]);
exit(EXIT_FAILURE);
}
bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
if (bufsize == -1) /* Value was indeterminate */
bufsize = 16384; /* Should be more than enough */
buf = malloc(bufsize);
if (buf == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
s = getpwnam_r(argv[1], &pwd, buf, bufsize, &result);
if (result == NULL) {
if (s == 0)
printf("Not found\n");
else {
errno = s;
perror("getpwnam_r");
}
exit(EXIT_FAILURE);
}
printf("Name: %s; UID: %ld\n", pwd.pw_gecos, (long) pwd.pw_uid);
exit(EXIT_SUCCESS);
}
Password file can be written only by root:
/ # ls -l /etc/passwd
-rw-r--r-- 1 root root 207 Jan 1 00:29 /etc/passwd
/ #
I also tried to run my program (test) with root rights, but it also failed when I gave it an existing username.
/ # /tmp/test admin
getpwnam_r: No such file or directory
/ #
1) So, what I forgot about, or what should do additionally?
2) Do I need to use /etc/shadow file for storing passwords for system users?
Update:
My passwd file is:
~ # cat /etc/passwd
root:b6MVch7fPLasN:0:0:root:/home/root:/bin/ash
admin:8Mt/Jtxcyg8AY:1000:1000:admin:/tmp:/tmp/cli
user:5v4HoPrA9NtUo:1001:1000:user:/tmp:/tmp/cli
~ #
Thanks in advance! Bakir
1) The search service or method used in the password database (/etc/passwd) is defined in /etc/nsswitch.conf. To use this service getpwnam function calls shared library in the lib directory: /lib/libnss_SERVICE.so.x, where SERVICE is the search method. In my case compat is default method because of absent of /etc/nsswitch.conf. So, I was need to add libnss_compat.so.2 to /lib.
strace is useful thing!
Many thanks to osqx and alk!

Resources