diff --git a/lib/libutil/Makefile b/lib/libutil/Makefile
index 001faf01ba48..47b728a5b136 100644
--- a/lib/libutil/Makefile
+++ b/lib/libutil/Makefile
@@ -7,7 +7,7 @@ CFLAGS+=-Wall -DLIBC_SCCS -I${.CURDIR} -I${.CURDIR}/../../sys
 #CFLAGS+=LOGIN_CAP_AUTH
 SRCS=	login.c login_tty.c logout.c logwtmp.c pty.c setproctitle.c \
 	login_cap.c login_class.c login_auth.c login_times.c login_ok.c \
-	_secure_path.c uucplock.c
+	_secure_path.c uucplock.c property.c auth.c
 MAN3+=	login.3 login_auth.3 login_tty.3 logout.3 logwtmp.3 pty.3 \
 	setproctitle.3 login_cap.3 login_class.3 login_times.3 login_ok.3 \
 	_secure_path.3 uucplock.3
diff --git a/lib/libutil/auth.c b/lib/libutil/auth.c
new file mode 100644
index 000000000000..db6246e3ff2e
--- /dev/null
+++ b/lib/libutil/auth.c
@@ -0,0 +1,68 @@
+/*
+ *
+ * Simple authentication database handling code.
+ *
+ * Copyright (c) 1998
+ *	Jordan Hubbard.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    verbatim and that no modifications are made prior to this
+ *    point in the file.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR HIS PETS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id*
+ *
+ */
+
+#include <stdio.h>
+#include <syslog.h>
+#include <libutil.h>
+
+static properties P;
+
+static int
+initauthconf(const char *path)
+{
+    FILE *fp;
+
+    if (!P) {
+	if ((fp = fopen(path, "r")) == NULL) {
+	    syslog(LOG_ERR, "initauthconf: unable to open file: %s", path);
+	    return 1;
+	}
+	P = properties_read(fp);
+	fclose(fp);
+	if (!P) {
+	    syslog(LOG_ERR, "initauthconf: unable to parse file: %s", path);
+	    return 1;
+	}
+    }
+    return 0;
+}
+
+char *
+auth_getval(const char *name)
+{
+    if (!P && initauthconf(_PATH_AUTHCONF))
+	return NULL;
+    else
+	return property_find(P, name);
+}
diff --git a/lib/libutil/libutil.h b/lib/libutil/libutil.h
index da128d90e800..f21cbb40fdfe 100644
--- a/lib/libutil/libutil.h
+++ b/lib/libutil/libutil.h
@@ -18,14 +18,25 @@
  * 5. Modifications may be freely made to this file providing the above
  *    conditions are met.
  *
- * $Id: libutil.h,v 1.15 1998/06/01 08:46:52 amurai Exp $
+ * $Id: libutil.h,v 1.16 1998/06/05 08:21:33 ache Exp $
  */
 
 #ifndef _LIBUTIL_H_
 #define	_LIBUTIL_H_
 
+#include <stdio.h>
 #include <sys/cdefs.h>
 
+/* for properties.c */
+typedef struct _property {
+	struct _property *next;
+	char *name;
+	char *value;
+} *properties;
+
+/* for auth.c */
+#define _PATH_AUTHCONF	"/etc/auth.conf"
+
 /* Avoid pulling in all the include files for no need */
 struct termios;
 struct winsize;
@@ -47,6 +58,10 @@ int	uu_lock __P((const char *_ttyname));
 int	uu_unlock __P((const char *_ttyname));
 int	uu_lock_txfr __P((const char *_ttyname, pid_t _pid));
 int	_secure_path __P((const char *_path, uid_t _uid, gid_t _gid));
+properties properties_read __P((FILE *fp));
+void	properties_free __P((properties list));
+char	*property_find __P((properties list, const char *name));
+char	*auth_getval __P((const char *name));
 __END_DECLS
 
 #define UU_LOCK_INUSE (1)
diff --git a/lib/libutil/property.c b/lib/libutil/property.c
new file mode 100644
index 000000000000..3a1b991614ba
--- /dev/null
+++ b/lib/libutil/property.c
@@ -0,0 +1,215 @@
+/*
+ *
+ * Simple property list handling code.
+ *
+ * Copyright (c) 1998
+ *	Jordan Hubbard.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    verbatim and that no modifications are made prior to this
+ *    point in the file.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR HIS PETS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libutil.h>
+
+#define MAX_NAME	64
+#define MAX_VALUE	512
+
+static properties
+property_alloc(char *name, char *value)
+{
+    properties n;
+
+    n = (properties)malloc(sizeof(struct _property));
+    n->next = NULL;
+    n->name = name ? strdup(name) : NULL;
+    n->value = value ? strdup(value) : NULL;
+    return n;
+}
+
+properties
+properties_read(FILE *fp)
+{
+    properties head, ptr;
+    char hold_n[MAX_NAME + 1];
+    char hold_v[MAX_VALUE + 1];
+    char buf[BUFSIZ * 4];
+    int bp, n, v, max;
+    enum { LOOK, COMMENT, NAME, VALUE, MVALUE, COMMIT, FILL, STOP } state;
+    int ch = 0;
+
+    n = v = bp = max = 0;
+    head = ptr = NULL;
+    state = LOOK;
+    while (state != STOP) {
+	if (state != COMMIT) {
+	    if (bp == max)
+		state = FILL;
+	    else
+		ch = buf[bp++];
+	}
+	switch(state) {
+	case FILL:
+	    if ((max = fread(buf, 1, sizeof buf, fp)) <= 0) {
+		state = STOP;
+		break;
+	    }
+	    else {
+		state = LOOK;
+		ch = buf[0];
+		bp = 1;
+	    }
+	    /* Fall through deliberately since we already have a character and state == LOOK */
+
+	case LOOK:
+	    if (isspace(ch))
+		continue;
+	    /* Allow shell or lisp style comments */
+	    else if (ch == '#' || ch == ';') {
+		state = COMMENT;
+		continue;
+	    }
+	    else if (isalnum(ch) || ch == '_') {
+		if (n >= MAX_NAME) {
+		    n = 0;
+		    state = COMMENT;
+		}
+		else {
+		    hold_n[n++] = ch;
+		    state = NAME;
+		}
+	    }
+	    else
+		state = COMMENT;	/* Ignore the rest of the line */
+	    break;
+
+	case COMMENT:
+	    if (ch == '\n')
+		state = LOOK;
+	    break;
+
+	case NAME:
+	    if (ch == '\n' || !ch) {
+		hold_n[n] = '\0';
+		hold_v[0] = '\0';
+		v = n = 0;
+		state = COMMIT;
+	    }
+	    else if (isspace(ch))
+		continue;
+	    else if (ch == '=') {
+		hold_n[n] = '\0';
+		v = n = 0;
+		state = VALUE;
+	    }
+	    else
+		hold_n[n++] = ch;
+	    break;
+
+	case VALUE:
+	    if (v == 0 && isspace(ch))
+		continue;
+	    else if (ch == '{')
+		state = MVALUE;
+	    else if (ch == '\n' || !ch) {
+		hold_v[v] = '\0';
+		v = n = 0;
+		state = COMMIT;
+	    }
+	    else {
+		if (v >= MAX_VALUE) {
+		    state = COMMENT;
+		    v = n = 0;
+		    break;
+		}
+		else
+		    hold_v[v++] = ch;
+	    }
+	    break;
+
+	case MVALUE:
+	    /* multiline value */
+	    if (v >= MAX_VALUE) {
+		state = COMMENT;
+		n = v = 0;
+	    }
+	    else if (ch == '}') {
+		hold_v[v] = '\0';
+		v = n = 0;
+		state = COMMIT;
+	    }
+	    else
+		hold_v[v++] = ch;
+	    break;
+
+	case COMMIT:
+	    if (!head)
+		head = ptr = property_alloc(hold_n, hold_v);
+	    else {
+		ptr->next = property_alloc(hold_n, hold_v);
+		ptr = ptr->next;
+	    }
+	    state = LOOK;
+	    v = n = 0;
+	    break;
+
+	case STOP:
+	    /* we don't handle this here, but this prevents warnings */
+	    break;
+	}
+    }
+    return head;
+}
+
+char *
+property_find(properties list, const char *name)
+{
+    if (!list || !name || !name[0])
+	return NULL;
+    while (list) {
+	if (!strcmp(list->name, name))
+	    return list->value;
+	list = list->next;
+    }
+    return NULL;
+}
+
+void
+properties_free(properties list)
+{
+    properties tmp;
+
+    while (list) {
+	tmp = list->next;
+	if (list->name)
+	    free(list->name);
+	if (list->value)
+	    free(list->value);
+	free(list);
+	list = tmp;
+    }
+}
+