Add login test program
authorSam Moore <[email protected]>
Sun, 29 Sep 2013 17:34:21 +0000 (01:34 +0800)
committerSam Moore <[email protected]>
Sun, 29 Sep 2013 17:34:21 +0000 (01:34 +0800)
So... it essentially mimics what /etc/shadow does. This might be easier than LDAP.

I was going to just use debian's login system, but realised some things:

POSIX C has a bunch of helpful functions that essentially parse /etc/passwd and provide a structure with all the relevant fields, like "pw_passwd".
Of course, the "pw_passwd" entry is always empty... because someone realised that storing hashes of passwords in /etc/passwd was not great :P

So /etc/passwd actually has no password information and is world readable, but /etc/shadow has everything (and is root readable only).
There are no wrapper functions for /etc/shadow because... user space programs aren't really meant to run as root.

Essentially linux was designed so that non-root programs can't fuck about with shell accounts. If you want to fuck about with shell accounts
you have to run as root and manually implement the parsing of /etc/shadow.

But I figured there was nothing stopping us from just making our own "shadow" file with hashed passwords.
That way people don't even need shell accounts. Well... the administrator needs to modify the file somehow...

LDAP probably gives more flexibility. It's probably better. Although it's also bloated.

To test the program, use the login "sonic" and the password "HEDGEHOG" (or something else to test failure).

testing/login/login.c [new file with mode: 0644]
testing/login/shadow [new file with mode: 0644]

diff --git a/testing/login/login.c b/testing/login/login.c
new file mode 100644 (file)
index 0000000..00bc0de
--- /dev/null
@@ -0,0 +1,117 @@
+#define _BSD_SOURCE
+#define _XOPEN_SOURCE
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <stdbool.h>
+
+// Compile with: gcc -std=c99 -lcrypt
+
+/** Deliberately make this smaller so we can test for buffer overflow problems **/
+#define BUFSIZ 50
+
+
+bool EnterTheShadowRealm(const char * shadow, const char * salt, const char * username, const char * passwd)
+{
+
+       if (strlen(username) + strlen(passwd) >= BUFSIZ-1)
+       {
+               fprintf(stderr, "User/Password too long!\n");
+               return false;
+       }
+
+       FILE * f = fopen(shadow, "r");
+       if (f == NULL)
+       {
+               fprintf(stderr, "Can't open %s - %s\n", shadow, strerror(errno));
+               return false;
+       }
+
+       char buffer[BUFSIZ];
+       int passwd_index = -1;
+       int garbage_index = -1;
+       while (fgets(buffer, BUFSIZ, f) != NULL) // NOTE: Restrict username+password strings to BUFSIZ... what could possibly go wrong?
+       {
+
+               printf("Scanning %d: %s", strlen(buffer), buffer);
+       
+               for (int i = 0; i < BUFSIZ-1; ++i)
+               {
+                       if (buffer[i] == ':')
+                       {
+                               buffer[i] = '\0';
+                               passwd_index = i+1;
+                               break;
+                       }
+               }
+
+               if (strcmp(username,buffer) == 0)
+               {
+                       printf("User matches! %s\n", buffer);
+                       break;
+               } 
+               passwd_index = -1;
+       }
+
+       if (passwd_index <= 0)
+       {
+               fprintf(stderr, "No user found matching %s\n", username);
+               return false;
+       }
+
+       for (int i = passwd_index; i < BUFSIZ-1; ++i)
+       {
+               if (buffer[i] == ':' || buffer[i] == '\n')
+               {
+                       buffer[i] = '\0';
+                       garbage_index = i+1;
+               }
+       }
+
+       printf("Salted Entry: %s\n", buffer+passwd_index);
+       printf("Salted Attempt: %s\n", crypt(passwd, salt));
+       
+       return (strcmp(crypt(passwd, salt), passwd) == 0);
+       
+}
+
+
+int main(int argc, char ** argv)
+{
+       char * shadow = "shadow";
+       if (argc > 1)
+       {
+               shadow = argv[1];
+       }
+
+
+       
+       
+       // Get the username and password
+       // Need to get these passed through HTTPS at some point
+       printf("Username: ");
+       char username[BUFSIZ];
+       if (fgets(username, BUFSIZ, stdin) != username)
+       {
+               fprintf(stderr, "Username too long!\n");
+               exit(EXIT_FAILURE);
+       }
+
+       username[strlen(username)-1] = '\0';
+
+       char * password = getpass("Password: "); //NOTE: getpass is deprecated. Just here for testing.
+       password[strlen(password)-1] = '\0';
+       
+       printf("Could we enter the shadow realm? %d\n", EnterTheShadowRealm(shadow, "A9", username, password));
+       
+       
+       
+       return 0;
+}
diff --git a/testing/login/shadow b/testing/login/shadow
new file mode 100644 (file)
index 0000000..88fd7d8
--- /dev/null
@@ -0,0 +1 @@
+sonic:A9joaLnTeTG0Q

UCC git Repository :: git.ucc.asn.au