diff options
author | Rob Landley <rob@landley.net> | 2012-07-17 08:54:47 -0500 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2012-07-17 08:54:47 -0500 |
commit | 2c917f5acc008e73b367ecf82402b5eac08db10c (patch) | |
tree | 6ce5d5675ad250648ce8c7828c642540f8587f70 /lib/password.c | |
parent | c8d0da5358832ab0e24bafc01b934b68f64ec12d (diff) | |
download | toybox-2c917f5acc008e73b367ecf82402b5eac08db10c.tar.gz |
Add passwd by Kyungwan Han.
Diffstat (limited to 'lib/password.c')
-rw-r--r-- | lib/password.c | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/lib/password.c b/lib/password.c new file mode 100644 index 00000000..2b11144e --- /dev/null +++ b/lib/password.c @@ -0,0 +1,142 @@ +/* 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_passwd(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_passwd(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; +} |