blob: 8221a022064e73c5bfc419c43262c4893da57c59 [file] [log] [blame]
/* vi: set sw=4 ts=4 :
* pwdutils.c - password read/update helper functions.
*
* Copyright 2012 Ashwini Kumar <ak.ashwini@gmail.com>
*/
#include "toys.h"
#include <time.h>
int read_password(char * buff, int buflen, char* mesg)
{
int i = 0;
struct termios termio, oldtermio;
tcgetattr(0, &oldtermio);
tcflush(0, TCIFLUSH);
termio = oldtermio;
termio.c_iflag &= ~(IUCLC|IXON|IXOFF|IXANY);
termio.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|TOSTOP);
tcsetattr(0, TCSANOW, &termio);
fputs(mesg, stdout);
fflush(stdout);
while (1) {
int ret = read(0, &buff[i], 1);
if ( ret < 0 ) {
buff[0] = 0;
tcsetattr(0, TCSANOW, &oldtermio);
return 1;
}
else if ( ret == 0 || buff[i] == '\n' ||
buff[i] == '\r' || buflen == i+1) {
buff[i] = '\0';
break;
}
i++;
}
tcsetattr(0, TCSANOW, &oldtermio);
puts("");
fflush(stdout);
return 0;
}
static char *get_nextcolon(const char *line, char delim)
{
char *current_ptr = NULL;
if((current_ptr = strchr(line, ':')) == NULL)
error_exit("Invalid Entry\n");
return current_ptr;
}
int update_password(char *filename, char* username, char* encrypted)
{
char *filenamesfx = NULL, *namesfx = NULL;
char *shadow = NULL, *sfx = NULL;
FILE *exfp, *newfp;
int ret = -1; //fail
struct flock lock;
char *line = NULL;
shadow = strstr(filename, "shadow");
filenamesfx = xmsprintf("%s+", filename);
sfx = strchr(filenamesfx, '+');
exfp = fopen(filename, "r+");
if(!exfp) {
perror_msg("Couldn't open file %s",filename);
goto free_storage;
}
*sfx = '-';
ret = unlink(filenamesfx);
ret = link(filename, filenamesfx);
if(ret < 0) error_msg("can't create backup file");
*sfx = '+';
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
ret = fcntl(fileno(exfp), F_SETLK, &lock);
if(ret < 0) perror_msg("Couldn't lock file %s",filename);
lock.l_type = F_UNLCK; //unlocking at a later stage
newfp = fopen(filenamesfx, "w+");
if(!newfp) {
error_msg("couldn't open file for writing");
ret = -1;
fclose(exfp);
goto free_storage;
}
ret = 0;
namesfx = xmsprintf("%s:",username);
while((line = get_line(fileno(exfp))) != NULL)
{
if(strncmp(line, namesfx, strlen(namesfx)) != 0)
fprintf(newfp, "%s\n", line);
else {
char *current_ptr = NULL;
fprintf(newfp, "%s%s:",namesfx,encrypted);
current_ptr = get_nextcolon(line, ':'); //past username
current_ptr++; //past colon ':' after username
current_ptr = get_nextcolon(current_ptr, ':'); //past passwd
current_ptr++; //past colon ':' after passwd
if(shadow) {
fprintf(newfp, "%u:",(unsigned)(time(NULL))/(24*60*60));
current_ptr = get_nextcolon(current_ptr, ':');
current_ptr++; //past time stamp colon.
fprintf(newfp, "%s\n",current_ptr);
}
else {
fprintf(newfp, "%s\n",current_ptr);
}
}
free(line);
}
free(namesfx);
fcntl(fileno(exfp), F_SETLK, &lock);
fclose(exfp);
errno = 0;
fflush(newfp);
fsync(fileno(newfp));
fclose(newfp);
rename(filenamesfx, filename);
if(errno) {
perror_msg("File Writing/Saving failed: ");
unlink(filenamesfx);
ret = -1;
}
free_storage:
free(filenamesfx);
return ret;
}