summaryrefslogtreecommitdiffstats
path: root/src/util/dict_unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/dict_unix.c')
-rw-r--r--src/util/dict_unix.c204
1 files changed, 204 insertions, 0 deletions
diff --git a/src/util/dict_unix.c b/src/util/dict_unix.c
new file mode 100644
index 0000000..4635344
--- /dev/null
+++ b/src/util/dict_unix.c
@@ -0,0 +1,204 @@
+/*++
+/* NAME
+/* dict_unix 3
+/* SUMMARY
+/* dictionary manager interface to UNIX tables
+/* SYNOPSIS
+/* #include <dict_unix.h>
+/*
+/* DICT *dict_unix_open(map, dummy, dict_flags)
+/* const char *map;
+/* int dummy;
+/* int dict_flags;
+/* DESCRIPTION
+/* dict_unix_open() makes the specified UNIX table accessible via
+/* the generic dictionary operations described in dict_open(3).
+/* The \fIdummy\fR argument is not used.
+/*
+/* Known map names:
+/* .IP passwd.byname
+/* The table is the UNIX password database. The key is a login name.
+/* The result is a password file entry in passwd(5) format.
+/* .IP group.byname
+/* The table is the UNIX group database. The key is a group name.
+/* The result is a group file entry in group(5) format.
+/* SEE ALSO
+/* dict(3) generic dictionary manager
+/* DIAGNOSTICS
+/* Fatal errors: out of memory, unknown map name, attempt to update map.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include "sys_defs.h"
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <pwd.h>
+#include <grp.h>
+
+/* Utility library. */
+
+#include "msg.h"
+#include "mymalloc.h"
+#include "vstring.h"
+#include "stringops.h"
+#include "dict.h"
+#include "dict_unix.h"
+
+/* Application-specific. */
+
+typedef struct {
+ DICT dict; /* generic members */
+} DICT_UNIX;
+
+/* dict_unix_getpwnam - find password table entry */
+
+static const char *dict_unix_getpwnam(DICT *dict, const char *key)
+{
+ struct passwd *pwd;
+ static VSTRING *buf;
+ static int sanity_checked;
+
+ dict->error = 0;
+
+ /*
+ * Optionally fold the key.
+ */
+ if (dict->flags & DICT_FLAG_FOLD_FIX) {
+ if (dict->fold_buf == 0)
+ dict->fold_buf = vstring_alloc(10);
+ vstring_strcpy(dict->fold_buf, key);
+ key = lowercase(vstring_str(dict->fold_buf));
+ }
+ if ((pwd = getpwnam(key)) == 0) {
+ if (sanity_checked == 0) {
+ sanity_checked = 1;
+ errno = 0;
+ if (getpwuid(0) == 0) {
+ msg_warn("cannot access UNIX password database: %m");
+ dict->error = DICT_ERR_RETRY;
+ }
+ }
+ return (0);
+ } else {
+ if (buf == 0)
+ buf = vstring_alloc(10);
+ sanity_checked = 1;
+ vstring_sprintf(buf, "%s:%s:%ld:%ld:%s:%s:%s",
+ pwd->pw_name, pwd->pw_passwd, (long) pwd->pw_uid,
+ (long) pwd->pw_gid, pwd->pw_gecos, pwd->pw_dir,
+ pwd->pw_shell);
+ return (vstring_str(buf));
+ }
+}
+
+/* dict_unix_getgrnam - find group table entry */
+
+static const char *dict_unix_getgrnam(DICT *dict, const char *key)
+{
+ struct group *grp;
+ static VSTRING *buf;
+ char **cpp;
+ static int sanity_checked;
+
+ dict->error = 0;
+
+ /*
+ * Optionally fold the key.
+ */
+ if (dict->flags & DICT_FLAG_FOLD_FIX) {
+ if (dict->fold_buf == 0)
+ dict->fold_buf = vstring_alloc(10);
+ vstring_strcpy(dict->fold_buf, key);
+ key = lowercase(vstring_str(dict->fold_buf));
+ }
+ if ((grp = getgrnam(key)) == 0) {
+ if (sanity_checked == 0) {
+ sanity_checked = 1;
+ errno = 0;
+ if (getgrgid(0) == 0) {
+ msg_warn("cannot access UNIX group database: %m");
+ dict->error = DICT_ERR_RETRY;
+ }
+ }
+ return (0);
+ } else {
+ if (buf == 0)
+ buf = vstring_alloc(10);
+ sanity_checked = 1;
+ vstring_sprintf(buf, "%s:%s:%ld:",
+ grp->gr_name, grp->gr_passwd, (long) grp->gr_gid);
+ for (cpp = grp->gr_mem; *cpp; cpp++) {
+ vstring_strcat(buf, *cpp);
+ if (cpp[1])
+ VSTRING_ADDCH(buf, ',');
+ }
+ VSTRING_TERMINATE(buf);
+ return (vstring_str(buf));
+ }
+}
+
+/* dict_unix_close - close UNIX map */
+
+static void dict_unix_close(DICT *dict)
+{
+ if (dict->fold_buf)
+ vstring_free(dict->fold_buf);
+ dict_free(dict);
+}
+
+/* dict_unix_open - open UNIX map */
+
+DICT *dict_unix_open(const char *map, int open_flags, int dict_flags)
+{
+ DICT_UNIX *dict_unix;
+ struct dict_unix_lookup {
+ char *name;
+ const char *(*lookup) (DICT *, const char *);
+ };
+ static struct dict_unix_lookup dict_unix_lookup[] = {
+ "passwd.byname", dict_unix_getpwnam,
+ "group.byname", dict_unix_getgrnam,
+ 0,
+ };
+ struct dict_unix_lookup *lp;
+
+ /*
+ * Sanity checks.
+ */
+ if (open_flags != O_RDONLY)
+ return (dict_surrogate(DICT_TYPE_UNIX, map, open_flags, dict_flags,
+ "%s:%s map requires O_RDONLY access mode",
+ DICT_TYPE_UNIX, map));
+
+ /*
+ * "Open" the database.
+ */
+ for (lp = dict_unix_lookup; /* void */ ; lp++) {
+ if (lp->name == 0)
+ return (dict_surrogate(DICT_TYPE_UNIX, map, open_flags, dict_flags,
+ "unknown table: %s:%s", DICT_TYPE_UNIX, map));
+ if (strcmp(map, lp->name) == 0)
+ break;
+ }
+ dict_unix = (DICT_UNIX *) dict_alloc(DICT_TYPE_UNIX, map,
+ sizeof(*dict_unix));
+ dict_unix->dict.lookup = lp->lookup;
+ dict_unix->dict.close = dict_unix_close;
+ dict_unix->dict.flags = dict_flags | DICT_FLAG_FIXED;
+ if (dict_flags & DICT_FLAG_FOLD_FIX)
+ dict_unix->dict.fold_buf = vstring_alloc(10);
+ dict_unix->dict.owner.status = DICT_OWNER_TRUSTED;
+
+ return (DICT_DEBUG (&dict_unix->dict));
+}