|
|
|
|
@ -1,6 +1,7 @@ |
|
|
|
|
/*
|
|
|
|
|
* @(#) pg_passwd.c 1.8 09:13:16 97/07/02 Y. Ichikawa |
|
|
|
|
* @(#) pg_passwd.c 1.8 09:13:16 97/07/02 Y. Ichikawa |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
#include <stdio.h> |
|
|
|
|
#include <stdlib.h> |
|
|
|
|
#include <string.h> |
|
|
|
|
@ -9,7 +10,8 @@ |
|
|
|
|
#include <errno.h> |
|
|
|
|
#include <sys/time.h> |
|
|
|
|
#include <ctype.h> |
|
|
|
|
#define issaltchar(c) (isalnum(c) || (c) == '.' || (c) == '/') |
|
|
|
|
#define issaltchar(c) (isalnum(c) || (c) == '.' || (c) == '/') |
|
|
|
|
|
|
|
|
|
#include "postgres.h" |
|
|
|
|
#ifdef HAVE_TERMIOS_H |
|
|
|
|
#include <termios.h> |
|
|
|
|
@ -17,9 +19,10 @@ |
|
|
|
|
#ifdef HAVE_CRYPT_H |
|
|
|
|
#include <crypt.h> |
|
|
|
|
#else |
|
|
|
|
extern char *crypt(const char *, const char *); |
|
|
|
|
extern char *crypt(const char *, const char *); |
|
|
|
|
#endif |
|
|
|
|
char *comname; |
|
|
|
|
|
|
|
|
|
char *comname; |
|
|
|
|
void usage(FILE *stream); |
|
|
|
|
void read_pwd_file(char *filename); |
|
|
|
|
void write_pwd_file(char *filename, char *bkname); |
|
|
|
|
@ -27,48 +30,298 @@ void encrypt_pwd(char key[9], char salt[3], char passwd[14]); |
|
|
|
|
int check_pwd(char key[9], char passwd[14]); |
|
|
|
|
void prompt_for_username(char *username); |
|
|
|
|
void prompt_for_password(char *prompt, char *password); |
|
|
|
|
|
|
|
|
|
void usage(FILE *stream) |
|
|
|
|
{ |
|
|
|
|
fprintf(stream, "Usage: %s <password file>\n", comname); |
|
|
|
|
fprintf(stream, "Usage: %s <password file>\n", comname); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
typedef struct { |
|
|
|
|
char *uname; |
|
|
|
|
char *pwd; |
|
|
|
|
char *rest; |
|
|
|
|
char *uname; |
|
|
|
|
char *pwd; |
|
|
|
|
char *rest; |
|
|
|
|
} pg_pwd; |
|
|
|
|
#define MAXPWDS 1024 |
|
|
|
|
pg_pwd pwds[MAXPWDS]; |
|
|
|
|
int npwds = 0; |
|
|
|
|
|
|
|
|
|
#define MAXPWDS 1024 |
|
|
|
|
|
|
|
|
|
pg_pwd pwds[MAXPWDS]; |
|
|
|
|
int npwds = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void read_pwd_file(char *filename) |
|
|
|
|
{ |
|
|
|
|
FILE *fp; |
|
|
|
|
static char line[512]; |
|
|
|
|
FILE *fp; |
|
|
|
|
static char line[512]; |
|
|
|
|
static char ans[128]; |
|
|
|
|
int i; |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
try_again: |
|
|
|
|
fp = fopen(filename, "r"); |
|
|
|
|
if (fp == NULL) { |
|
|
|
|
if (errno == ENOENT) { |
|
|
|
|
printf("File \"%s\" does not exist. Create? (y/n): ", filename); |
|
|
|
|
fflush(stdout); |
|
|
|
|
fgets(ans, 128, stdin); |
|
|
|
|
switch (ans[0]) { |
|
|
|
|
case 'y': case 'Y': |
|
|
|
|
fp = fopen(filename, "w"); |
|
|
|
|
if (fp == NULL) { |
|
|
|
|
perror(filename); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
fclose(fp); |
|
|
|
|
goto try_again; |
|
|
|
|
default: |
|
|
|
|
/* cannot continue */ |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
perror(filename); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
if (errno == ENOENT) { |
|
|
|
|
printf("File \"%s\" does not exist. Create? (y/n): ", filename); |
|
|
|
|
fflush(stdout); |
|
|
|
|
fgets(ans, 128, stdin); |
|
|
|
|
switch (ans[0]) { |
|
|
|
|
case 'y': case 'Y': |
|
|
|
|
fp = fopen(filename, "w"); |
|
|
|
|
if (fp == NULL) { |
|
|
|
|
perror(filename); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
fclose(fp); |
|
|
|
|
goto try_again; |
|
|
|
|
default: |
|
|
|
|
/* cannot continue */ |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
perror(filename); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* read all the entries */ |
|
|
|
|
for (npwds = 0; npwds < MAXPWDS && fgets(line, 512, fp) != NULL; ++npwds) |
|
|
|
|
for (npwds = 0; npwds < MAXPWDS && fgets(line, 512, fp) != NULL; ++npwds) { |
|
|
|
|
int l; |
|
|
|
|
char *p, *q; |
|
|
|
|
l = strlen(line); |
|
|
|
|
if (line[l-1] == '\n') |
|
|
|
|
line[l-1] = '\0'; |
|
|
|
|
else { /* too long */
|
|
|
|
|
fprintf(stderr, "%s: line %d: line too long.\n", |
|
|
|
|
filename, npwds + 1); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* get user name */ |
|
|
|
|
p = line; |
|
|
|
|
if ((q = index(p, ':')) == NULL) { |
|
|
|
|
fprintf(stderr, "%s: line %d: illegal format.\n", |
|
|
|
|
filename, npwds + 1); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
*(q++) = '\0'; |
|
|
|
|
if (strlen(p) == 0) { |
|
|
|
|
fprintf(stderr, "%s: line %d: null user name.\n", |
|
|
|
|
filename, npwds + 1); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
pwds[npwds].uname = strdup(p); |
|
|
|
|
|
|
|
|
|
/* check duplicate */ |
|
|
|
|
for (i = 0; i < npwds; ++i) { |
|
|
|
|
if (strcmp(pwds[i].uname, pwds[npwds].uname) == 0) { |
|
|
|
|
fprintf(stderr, "%s: duplicated entry.\n", pwds[npwds].uname); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* get password field */ |
|
|
|
|
p = q; |
|
|
|
|
q = index(p, ':'); |
|
|
|
|
/*
|
|
|
|
|
* --- don't care ----- |
|
|
|
|
if ((q = index(p, ':')) == NULL) { |
|
|
|
|
fprintf(stderr, "%s: line %d: illegal format.\n", |
|
|
|
|
filename, npwds + 1); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
if (q != NULL) *(q++) = '\0'; |
|
|
|
|
if (strlen(p) != 13) { |
|
|
|
|
fprintf(stderr, "WARNING: %s: line %d: illegal password length.\n", |
|
|
|
|
filename, npwds + 1); |
|
|
|
|
} |
|
|
|
|
pwds[npwds].pwd = strdup(p); |
|
|
|
|
|
|
|
|
|
/* rest of the line is treated as is */ |
|
|
|
|
if (q == NULL) |
|
|
|
|
pwds[npwds].rest = NULL; |
|
|
|
|
else |
|
|
|
|
pwds[npwds].rest = strdup(q); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fclose(fp); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void write_pwd_file(char *filename, char *bkname) |
|
|
|
|
{ |
|
|
|
|
FILE* fp; |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
/* make the backup file */ |
|
|
|
|
link_again: |
|
|
|
|
if (link(filename, bkname)) { |
|
|
|
|
if (errno == EEXIST) { |
|
|
|
|
unlink(bkname); |
|
|
|
|
goto link_again; |
|
|
|
|
} |
|
|
|
|
perror(bkname); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
if (unlink(filename)) { |
|
|
|
|
perror(filename); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* open file */ |
|
|
|
|
if ((fp = fopen(filename, "w")) == NULL) { |
|
|
|
|
perror(filename); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* write file */ |
|
|
|
|
for (i = 0; i < npwds; ++i) { |
|
|
|
|
fprintf(fp, "%s:%s%s%s\n", pwds[i].uname, pwds[i].pwd, |
|
|
|
|
pwds[i].rest ? ":" : "", |
|
|
|
|
pwds[i].rest ? pwds[i].rest : ""); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fclose(fp); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void encrypt_pwd(char key[9], char salt[3], char passwd[14]) |
|
|
|
|
{ |
|
|
|
|
int n; |
|
|
|
|
|
|
|
|
|
/* get encrypted password */ |
|
|
|
|
if (salt[0] == '\0') { |
|
|
|
|
struct timeval tm; |
|
|
|
|
gettimeofday(&tm, NULL); |
|
|
|
|
srand(tm.tv_sec ? tm.tv_sec : 1); |
|
|
|
|
do { |
|
|
|
|
n = rand() % 256; |
|
|
|
|
} while (! issaltchar(n)); |
|
|
|
|
salt[0] = n; |
|
|
|
|
do { |
|
|
|
|
n = rand() % 256; |
|
|
|
|
} while (! issaltchar(n)); |
|
|
|
|
salt[1] = n; |
|
|
|
|
salt[2] = '\0'; |
|
|
|
|
} |
|
|
|
|
strcpy(passwd, crypt(key, salt)); |
|
|
|
|
|
|
|
|
|
/* show it */ |
|
|
|
|
/* fprintf(stderr, "key = %s, salt = %s, password = %s\n",
|
|
|
|
|
key, salt, passwd); */ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int check_pwd(char key[9], char passwd[14]) |
|
|
|
|
{ |
|
|
|
|
char shouldbe[14]; |
|
|
|
|
char salt[3]; |
|
|
|
|
|
|
|
|
|
salt[0] = passwd[0]; |
|
|
|
|
salt[1] = passwd[1]; |
|
|
|
|
salt[2] = '\0'; |
|
|
|
|
encrypt_pwd(key, salt, shouldbe); |
|
|
|
|
|
|
|
|
|
return strncmp(shouldbe, passwd, 13) == 0 ? 1 : 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void prompt_for_username(char *username) |
|
|
|
|
{ |
|
|
|
|
int length; |
|
|
|
|
|
|
|
|
|
printf("Username: "); |
|
|
|
|
fgets(username, 9, stdin); |
|
|
|
|
length = strlen(username); |
|
|
|
|
|
|
|
|
|
/* skip rest of the line */ |
|
|
|
|
if (length > 0 && username[length-1] != '\n') { |
|
|
|
|
static char buf[512]; |
|
|
|
|
do { |
|
|
|
|
fgets(buf, 512, stdin); |
|
|
|
|
} while (buf[strlen(buf)-1] != '\n'); |
|
|
|
|
} |
|
|
|
|
if(length > 0 && username[length-1] == '\n') username[length-1] = '\0'; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void prompt_for_password(char *prompt, char *password) |
|
|
|
|
{ |
|
|
|
|
int length; |
|
|
|
|
#ifdef HAVE_TERMIOS_H |
|
|
|
|
struct termios t_orig, t; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
printf(prompt); |
|
|
|
|
#ifdef HAVE_TERMIOS_H |
|
|
|
|
tcgetattr(0, &t); |
|
|
|
|
t_orig = t; |
|
|
|
|
t.c_lflag &= ~ECHO; |
|
|
|
|
tcsetattr(0, TCSADRAIN, &t); |
|
|
|
|
#endif |
|
|
|
|
fgets(password, 9, stdin); |
|
|
|
|
#ifdef HAVE_TERMIOS_H |
|
|
|
|
tcsetattr(0, TCSADRAIN, &t_orig); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
length = strlen(password); |
|
|
|
|
/* skip rest of the line */ |
|
|
|
|
if (length > 0 && password[length-1] != '\n') { |
|
|
|
|
static char buf[512]; |
|
|
|
|
do { |
|
|
|
|
fgets(buf, 512, stdin); |
|
|
|
|
} while (buf[strlen(buf)-1] != '\n'); |
|
|
|
|
} |
|
|
|
|
if(length > 0 && password[length-1] == '\n') password[length-1] = '\0'; |
|
|
|
|
printf("\n"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int main(int argc, char *argv[]) |
|
|
|
|
{ |
|
|
|
|
static char bkname[512]; |
|
|
|
|
char username[9]; |
|
|
|
|
char salt[3]; |
|
|
|
|
char key[9], key2[9]; |
|
|
|
|
char e_passwd[14]; |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
comname = argv[0]; |
|
|
|
|
if (argc != 2) { |
|
|
|
|
usage(stderr); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* open file */ |
|
|
|
|
read_pwd_file(argv[1]); |
|
|
|
|
|
|
|
|
|
/* ask for the user name and the password */ |
|
|
|
|
prompt_for_username(username); |
|
|
|
|
prompt_for_password("New password: ", key); |
|
|
|
|
prompt_for_password("Re-enter new password: ", key2); |
|
|
|
|
if (strncmp(key, key2, 8) != 0) { |
|
|
|
|
fprintf(stderr, "Password mismatch.\n"); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
salt[0] = '\0'; |
|
|
|
|
encrypt_pwd(key, salt, e_passwd); |
|
|
|
|
|
|
|
|
|
/* check password entry */ |
|
|
|
|
for (i = 0; i < npwds; ++i) { |
|
|
|
|
if (strcmp(pwds[i].uname, username) == 0) { /* found */ |
|
|
|
|
pwds[i].pwd = strdup(e_passwd); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
}
|
|
|
|
|
if (i == npwds) { /* did not exist */ |
|
|
|
|
if (npwds == MAXPWDS) { |
|
|
|
|
fprintf(stderr, "%s: cannot handle so may entries.\n", comname); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
pwds[npwds].uname = strdup(username); |
|
|
|
|
pwds[npwds].pwd = strdup(e_passwd); |
|
|
|
|
pwds[npwds].rest = NULL; |
|
|
|
|
++npwds; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* write back the file */ |
|
|
|
|
sprintf(bkname, "%s.bk", argv[1]); |
|
|
|
|
write_pwd_file(argv[1], bkname); |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|