I can be able to let people login with root credentials to my gui in php?
If you mean the GUI process has root credentials, then yes. That is a requirement. passwd
and other things that do this have the setuid bit set and are owned by root. For instructions on how to do this with php see here.
First to make sure a basic fact about passwords is clear -- I think you probably already know this but: Passwords are not stored in the system. A one way hash of them is. A one way hash is a string that can be created using an encryption algorithm from a source string (e.g., an actual password) but the source cannot be recreated from the hash.
This means even if someone gets hold of /etc/shadow
, there's no way for them to reconstruct user passwords. The encryption is one way, it cannot be reversed. However, you can take a string, encrypt it the same way, and compare it to the hash. This is how password authentication happens.
The structure of the hash string in /etc/shadow
is explained in Anthon's good answer. Below is the basic process of authentication demonstrated in C. PHP has a wrapper for getpwnam()
or you could parse and store /etc/shadow
yourself. To understand what crypt()
does with the string (as Anthon mentions, it includes an indication of the algorithm used and the "salt" for creating the hash), see NOTES -> Glibc notes in man 3 crypt
. PHP's crypt()
appears to work the same way although the doc is less clear.
The only significant functions are getpwnam()
and crypt()
, everything else is just basic input, output, and string manipulation.
#define _XOPEN_SOURCE // Important.
#include <errno.h>
#include <crypt.h>
#include <shadow.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main (int argc, const char *argv[]) {
if (argc < 2) {
puts("Username required.");
return 1;
}
// Get shadow password.
struct spwd *spw = getspnam(argv[1]);
if (!spw) {
if (errno == EACCES) puts("Permission denied.");
else if (!errno) puts("No such user.");
else puts(strerror(errno));
return 1;
}
// Read password from user.
fprintf(stderr, "%s> ", argv[1]);
char buffer[4096];
int len = read(0, buffer, 4095);
// Ditch the newline.
buffer[len - 1] = '\0';
// Hash and report.
char *hashed = crypt(buffer, spw->sp_pwdp);
printf("%s\n%s\n", spw->sp_pwdp, hashed);
if (!strcmp(spw->sp_pwdp, hashed)) puts("Password matched.");
else puts("Password DID NOT match.");
return 0;
}
You can compile this:
gcc --std=c99 whatever.c -o testpw -lcrypt
You need to run it as root or you will get "Permission denied." You need to specify a real username:
./testpw me
Note echo is not disabled so the password will be visible when you type it.