2

I'm trying to write a C program to change a user password using Linux system calls. I have tryed to use the /etc/passwd and /etc/shadow files but I'm having problems because the password is encrypted, can you help me to solve this?

void main (int argc, char **argv) {

uid_t uid;

struct passwd *pw;

uid = getuid();

if (argc > 1)
    pw = getpwnam(argv[1]);
else
    pw = getpwuid(uid);
//system("passwd");
//printf("%i",execl("/usr/bin/passwd","passwd",pw->pw_name)); //here I tried to use execl but it returns error

}

I used system("passwd") but I don't think my teacher will accept that. On the rest of it I was just trying to understand the getpw... stuff, it's not important.

Damares Oliveira
  • 143
  • 2
  • 12
  • What have you tried? What's your code? There isn't a standard system call to do it; the logic is encapsulated in the `passwd` program, and one or two others. (So, maybe the system call you need is the `system()` statement that runs the `passwd` program.) – Jonathan Leffler Apr 02 '12 at 15:14
  • 1
    "passwd" is good enough and it's dangerous for to be dealing with those files without complete understanding. Otherwise, you may compromise security. Besides, I don't see any use-case for your own "passwd" command. – P.P Apr 02 '12 at 15:17

2 Answers2

3

You can try to use putpwent for this. As Jonathan Leffler said in the comments, you need putspent if you want to update the shadow file.

But the easiest and probably the most portable way to do this would be to just call passwd via system(3) or popen(3).

cnicutar
  • 178,505
  • 25
  • 365
  • 392
  • You'd need to use [`putspent()`](http://linux.die.net/man/3/putspent) or similar for `/etc/shadow`. Does anyone still include the encrypted password in `/etc/passwd`? – Jonathan Leffler Apr 02 '12 at 15:16
  • @JonathanLeffler I thought putpwent updates shadow, let me check. – cnicutar Apr 02 '12 at 15:17
  • @JonathanLeffler No, indeed it doesn't seem to update shadow. Indeed it's intended for "general" passwd files, not for `/etc/passwd` only. `system(3)` seems the way to go for this one. – cnicutar Apr 02 '12 at 15:22
  • The `*sp*` series of `get` and `put` functions works on the shadow password file; it could be used. I think using the `passwd` program is best (updating the last changed field etc is, tricky; the coding is not obvious). – Jonathan Leffler Apr 02 '12 at 15:23
  • @JonathanLeffler I guess I didn't read your first comment carefully. Didn't know about `putspent` :-). – cnicutar Apr 02 '12 at 15:25
1

The first thing I learned when I started writing software on Linux after coming from a background in Windows and OS X development is that command line utilities are to be embraced, not shunned. Even for things that have the option of using a C api or a command line utility, it's often smarter and more reliable to fork and exec (do NOT popen unless you don't care to check whether or not the return code is 0!) than to use the C api.

In fact, calling a command line utility is no different than calling a C api unless you need to eke out every last bit of performance in your application. It's practically an API where the function name is the utility name and the parameters are the command line arguments.

So in answer to your question: try exec passwd and it'll take care of all your issues.

Mahmoud Al-Qudsi
  • 28,357
  • 12
  • 85
  • 125
  • 1
    Except that you need to pass the new password text via command-line arguments, which are visible in the process list, which is bad for security. This situation may be the one exception to what you're saying about fork and exec, due to security concerns. – deltamind106 May 20 '19 at 18:28