More work on password support for the menu systems. Make the base64
authorhpa <hpa>
Fri, 21 Jan 2005 00:49:46 +0000 (00:49 +0000)
committerhpa <hpa>
Fri, 21 Jan 2005 00:49:46 +0000 (00:49 +0000)
decoder work (necessary to handle encrypted passwords.)  Simple
SHA-1 password generator in Perl.

com32/include/netinet/in.h
com32/libutil/Makefile
com32/libutil/include/base64.h [new file with mode: 0644]
com32/libutil/include/sha1.h
com32/libutil/sha1hash.c
com32/libutil/unbase64.c [new file with mode: 0644]
com32/modules/menu.c
com32/modules/menu.h
com32/modules/readconfig.c
sha1pass [new file with mode: 0755]

index dc11448..325bd4c 100644 (file)
@@ -27,7 +27,7 @@ static inline uint32_t __htonl(uint32_t v)
 }
 
 #define htonl(x) __htonl(x)
-#define ntohl(x) __ntohl(x)
+#define ntohl(x) __htonl(x)
 
 static inline uint64_t __htonq(uint64_t v)
 {
@@ -35,7 +35,7 @@ static inline uint64_t __htonq(uint64_t v)
 }
 
 #define htonq(x) __htonq(x)
-#define ntohq(x) __ntohq(x)
+#define ntohq(x) __htonq(x)
 
 #endif /* _NETINET_IN_H */
 
index 9003f98..b9d19a5 100644 (file)
@@ -47,7 +47,7 @@ LNXCFLAGS  = -I./include -W -Wall -O -g
 LNXSFLAGS  = -g
 LNXLDFLAGS = -g
 OBJCOPY    = objcopy
-LIBOBJS           = ansiline.o ansiraw.o get_key.o idle.o
+LIBOBJS           = ansiline.o ansiraw.o get_key.o idle.o sha1hash.o unbase64.o
 LNXLIBOBJS = $(patsubst %.o,%.lo,$(LIBOBJS))
 
 .SUFFIXES: .lss .c .lo .o .elf .c32 .lnx
diff --git a/com32/libutil/include/base64.h b/com32/libutil/include/base64.h
new file mode 100644 (file)
index 0000000..45c69af
--- /dev/null
@@ -0,0 +1,42 @@
+#ident "$Id$"
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2005 H. Peter Anvin - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *   
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *   
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * base64.h
+ *
+ * Simple routines for handing base64 text
+ */
+
+#ifndef LIBUTIL_BASE64_H
+#define LIBUTIL_BASE64_H
+
+#include <stddef.h>
+
+size_t unbase64(unsigned char *, size_t, const char *);
+
+#endif
index 7f08ced..ea324c7 100644 (file)
@@ -1,15 +1,17 @@
 #ifndef LIBUTIL_SHA1_H
 #define LIBUTIL_SHA1_H
 
+#include <stdint.h>
+
 typedef struct {
     uint32_t state[5];
     uint32_t count[2];
     unsigned char buffer[64];
 } SHA1_CTX;
 
-void SHA1Transform(uint32_t state[5], unsigned char buffer[64]);
+void SHA1Transform(uint32_t state[5], const unsigned char buffer[64]);
 void SHA1Init(SHA1_CTX* context);
-void SHA1Update(SHA1_CTX* context, unsigned char* data, uint32_t len);  /*
+void SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len);  /*
 JHB */
 void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
 
index 6656b7d..fc5cc35 100644 (file)
@@ -114,7 +114,7 @@ void SHAPrintContext(SHA1_CTX *context, char *msg){
 
 /* Hash a single 512-bit block. This is the core of the algorithm. */
 
-void SHA1Transform(uint32_t state[5], unsigned char buffer[64])
+void SHA1Transform(uint32_t state[5], const unsigned char buffer[64])
 {
 uint32_t a, b, c, d, e;
 typedef union {
@@ -183,7 +183,7 @@ void SHA1Init(SHA1_CTX* context)
 
 /* Run your data through this. */
 
-void SHA1Update(SHA1_CTX* context, unsigned char* data, uint32_t len)  /*
+void SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len)    /*
 JHB */
 {
 uint32_t i, j; /* JHB */
diff --git a/com32/libutil/unbase64.c b/com32/libutil/unbase64.c
new file mode 100644 (file)
index 0000000..83007d3
--- /dev/null
@@ -0,0 +1,78 @@
+#ident "$Id$"
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2005 H. Peter Anvin - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *   
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *   
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * unbase64.c
+ *
+ * Convert a string in base64 format to a byte array.
+ */
+
+#include <string.h>
+#include <base64.h>
+
+static const unsigned char _base64chars[] =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./";
+
+size_t unbase64(unsigned char *buffer, size_t bufsiz, const char *txt)
+{
+  unsigned int bits = 0;
+  int nbits = 0;
+  char base64tbl[256];
+  int i;
+  char v;
+  size_t nbytes = 0;
+
+  
+  memset(base64tbl, -1, sizeof base64tbl);
+
+  for ( i = 0 ; _base64chars[i] ; i++ ) {
+    base64tbl[_base64chars[i]] = i;
+  }
+  
+  /* Also support filesystem safe alternate base64 encoding */
+  base64tbl['-'] = 62;
+  base64tbl['_'] = 63;
+
+  while ( *txt ) {
+    if ( (v = base64tbl[(unsigned char) *txt]) >= 0 ) {
+      bits <<= 6;
+      bits += v;
+      nbits += 6;
+      if ( nbits >= 8 ) {
+       if ( nbytes < bufsiz )
+         *buffer++ = (bits >> (nbits-8));
+       nbytes++;
+       nbits -= 8;
+      }
+    }      
+    txt++;
+  }
+
+  return nbytes;
+}
+
index e652766..83d8b5b 100644 (file)
@@ -29,6 +29,7 @@
 #include <sys/times.h>
 #include <unistd.h>
 #include <sha1.h>
+#include <base64.h>
 #ifdef __COM32__
 #include <com32.h>
 #endif
@@ -52,7 +53,7 @@ struct menu_attrib {
   const char *cmdline;         /* Command line */
   const char *screen;          /* Rest of the screen */
   const char *pwdborder;       /* Password box border */
-  const char *pwdhdr;          /* Password box header */
+  const char *pwdheader;       /* Password box header */
   const char *pwdentry;                /* Password box contents */
 };
 
@@ -166,23 +167,41 @@ draw_row(int y, int sel, int top, int sbtop, int sbbot)
 }
 
 static int
-passwd_compare(const char *entry, const char *passwd)
+passwd_compare(const char *passwd, const char *entry)
 {
   const char *p;
   SHA1_CTX ctx;
+  unsigned char sha1[20], pwdsha1[20];
 
   if ( passwd[0] != '$' )      /* Plaintext passwd, yuck! */
     return !strcmp(entry, passwd);
 
-  if ( strncmp(passwd, "$2$", 3) )
+  if ( strncmp(passwd, "$4$", 3) )
     return 0;                  /* Only SHA-1 passwds supported */
 
-  if ( p = 
+  SHA1Init(&ctx);
+
+  if ( (p = strchr(passwd+3, '$')) ) {
+    SHA1Update(&ctx, passwd+3, p-(passwd+3));
+    p++;
+  } else {
+    p = passwd+3;              /* Assume no salt */
+  }
+
+  SHA1Update(&ctx, entry, strlen(entry));
+  SHA1Final(sha1, &ctx);
+
+  memset(pwdsha1, 0, 20);
+  unbase64(pwdsha1, 20, p);
+
+  return !memcmp(sha1, pwdsha1, 20);
+}
 
 static int
 ask_passwd(const struct menu_entry *entry)
 {
-  const char title[] = "Password required";
+  static const char title[] = "Password required";
+  static char user_passwd[] = "passw0rd";
   int x;
 
   printf("\033[%d;%dH%s\016l", PASSWD_ROW, PASSWD_MARGIN+1,
@@ -200,12 +219,16 @@ ask_passwd(const struct menu_entry *entry)
   
   printf("j\017\033[%d;%dH%s %s \033[%d;%dH%s",
         PASSWD_ROW, WIDTH-(sizeof(title)+1)/2,
-        menu_attrib->pwdtitle, title,
+        menu_attrib->pwdheader, title,
         PASSWD_ROW+1, PASSWD_MARGIN+3, menu_attrib->pwdentry);
 
   /* Actually allow user to type a password, then compare to the SHA1 */
-
-  return 0;
+  if ( (menu_master_passwd && passwd_compare(menu_master_passwd, user_passwd))
+       || (entry && entry->passwd &&
+          passwd_compare(entry->passwd, user_passwd)) )
+    return 1;
+  else
+    return 0;
 }
 
 
index e38c612..02df13a 100644 (file)
@@ -41,6 +41,7 @@ extern int timeout;
 
 extern char *menu_title;
 extern char *ontimeout;
+extern char *menu_master_passwd;
 
 void parse_config(const char *filename);
 
index b3314a7..82b2c56 100644 (file)
@@ -31,6 +31,8 @@ int timeout   = 0;
 char *menu_title  = "";
 char *ontimeout   = NULL;
 
+char *menu_master_passwd = NULL;
+
 struct menu_entry menu_entries[MAX_ENTRIES];
 struct menu_entry *menu_hotkeys[256];
 
diff --git a/sha1pass b/sha1pass
new file mode 100755 (executable)
index 0000000..10ec8b5
--- /dev/null
+++ b/sha1pass
@@ -0,0 +1,29 @@
+#!/usr/bin/perl
+
+use bytes;
+use Digest::SHA1;
+use MIME::Base64;
+
+sub random_bytes($) {
+    my($n) = @_;
+    my($v, $i);
+    
+    if ( open(RANDOM, '<', '/dev/random') ||
+        open(RANDOM, '<', '/dev/urandom') ) {
+       read(RANDOM, $v, $n);
+    } else {
+       # No real RNG available...
+       srand($$ ^ time);
+       $v = '';
+       for ( $i = 0 ; $i < $n ; $i++ ) {
+           $v .= ord(int(rand() * 256));
+       }
+    }
+
+    return $v;
+}
+
+$salt = MIME::Base64::encode(random_bytes(6), '');
+$pass = Digest::SHA1::sha1_base64($salt, $ARGV[0]);
+
+print '$4$', $salt, '$', $pass, "\$\n";