From 86062218daac3d0d5a1a275ae6c37f2532a09220 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Mon, 25 Aug 1997 23:11:21 +0000
Subject: [PATCH] pg_passwd cleanup.

---
 contrib/datetime/Makefile     |  12 ++
 src/bin/pg_passwd/pg_passwd.c | 325 ++++++++++++++++++++++++++++++----
 2 files changed, 301 insertions(+), 36 deletions(-)
 create mode 100644 contrib/datetime/Makefile

diff --git a/contrib/datetime/Makefile b/contrib/datetime/Makefile
new file mode 100644
index 00000000000..930d6e57cfd
--- /dev/null
+++ b/contrib/datetime/Makefile
@@ -0,0 +1,12 @@
+D=/usr/postgres
+P=$D/lib/datetime_functions.so
+CFLAGS=-fpic -O -I../../src/include -I../../src/backend
+
+all: $P datetime_functions.sql
+
+$P:datetime_functions.o 
+	ld -Bshareable -o $P datetime_functions.o 
+
+datetime_functions.sql: datetime.prot
+	sh datetime.prot $P
+	psql -c "\idatetime_functions.sql" template1
diff --git a/src/bin/pg_passwd/pg_passwd.c b/src/bin/pg_passwd/pg_passwd.c
index e68146a805f..c1e752a586f 100644
--- a/src/bin/pg_passwd/pg_passwd.c
+++ b/src/bin/pg_passwd/pg_passwd.c
@@ -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;
+}
-- 
GitLab