Index: src/daemon.c
--- src/daemon.c.orig
+++ src/daemon.c
@@ -38,6 +38,10 @@
 #include <errno.h>
 #include <sys/types.h>
 
+#ifdef __OpenBSD__
+#include <grp.h> /* getgrnam */
+#endif
+
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <glib-object.h>
@@ -105,11 +109,18 @@ typedef struct
         GHashTable      *extension_ifaces;
 } DaemonPrivate;
 
+#ifdef HAVE_SHADOW_H
 typedef struct passwd * (* EntryGeneratorFunc) (Daemon *,
                                                 GHashTable *,
                                                 GHashTable *,
                                                 gpointer *,
                                                 struct spwd **shadow_entry);
+#else
+typedef struct passwd * (* EntryGeneratorFunc) (Daemon *,
+                                                GHashTable *,
+                                                GHashTable *,
+                                                gpointer *);
+#endif
 
 typedef struct
 {
@@ -215,20 +226,30 @@ remove_cache_files (const gchar *user_name)
         g_remove (icon_filename);
 }
 
+#ifdef HAVE_SHADOW_H
 static struct passwd *
 entry_generator_fgetpwent (Daemon       *daemon,
                            GHashTable   *users,
                            GHashTable   *local_users,
                            gpointer     *state,
                            struct spwd **spent)
+#else
+static struct passwd *
+entry_generator_fgetpwent (Daemon       *daemon,
+                           GHashTable   *users,
+                           GHashTable   *local_users,
+                           gpointer     *state)
+#endif
 {
         struct passwd *pwent;
 
+#if HAVE_SHADOW_H
         struct
         {
                 struct spwd spbuf;
                 char        buf[1024];
         } *shadow_entry_buffers;
+#endif
 
         struct
         {
@@ -242,10 +263,13 @@ entry_generator_fgetpwent (Daemon       *daemon,
 
         /* First iteration */
         if (*state == NULL) {
+#ifdef HAVE_SHADOW_H
                 GHashTable *shadow_users = NULL;
                 g_autofree char *shadow_path = NULL;
+#endif
                 g_autofree char *passwd_path = NULL;
                 FILE *fp;
+#ifdef HAVE_SHADOW_H
                 struct spwd *shadow_entry;
 
                 shadow_path = g_build_filename (get_sysconfdir (), PATH_SHADOW, NULL);
@@ -281,18 +305,23 @@ entry_generator_fgetpwent (Daemon       *daemon,
                         g_clear_pointer (&shadow_users, g_hash_table_unref);
                         return NULL;
                 }
+#endif
 
                 passwd_path = g_build_filename (get_sysconfdir (), PATH_PASSWD, NULL);
                 fp = fopen (passwd_path, "r");
                 if (fp == NULL) {
+#ifdef HAVE_SHADOW_H
                         g_clear_pointer (&shadow_users, g_hash_table_unref);
+#endif
                         g_warning ("Unable to open %s: %s", passwd_path, g_strerror (errno));
                         return NULL;
                 }
 
                 generator_state = g_malloc0 (sizeof(*generator_state));
                 generator_state->fp = fp;
+#ifdef HAVE_SHADOW_H
                 generator_state->shadow_users = shadow_users;
+#endif
 
                 *state = generator_state;
         }
@@ -303,17 +332,23 @@ entry_generator_fgetpwent (Daemon       *daemon,
         if (g_hash_table_size (users) < MAX_LOCAL_USERS) {
                 pwent = fgetpwent (generator_state->fp);
                 if (pwent != NULL) {
+#ifdef HAVE_SHADOW_H
                         shadow_entry_buffers = g_hash_table_lookup (generator_state->shadow_users, pwent->pw_name);
 
                         if (shadow_entry_buffers != NULL) {
                                 *spent = &shadow_entry_buffers->spbuf;
                         }
+#endif
 
                         /* Skip system users... */
                         if (!user_classify_is_human (pwent->pw_uid, pwent->pw_name, pwent->pw_shell)) {
                                 g_debug ("skipping user: %s", pwent->pw_name);
 
+#ifdef HAVE_SHADOW_H
                                 return entry_generator_fgetpwent (daemon, users, local_users, state, spent);
+#else
+                                return entry_generator_fgetpwent (daemon, users, local_users, state);
+#endif
                         }
 
                         return pwent;
@@ -321,19 +356,29 @@ entry_generator_fgetpwent (Daemon       *daemon,
         }
 
         fclose (generator_state->fp);
+#ifdef HAVE_SHADOW_H
         g_hash_table_unref (generator_state->shadow_users);
+#endif
         g_free (generator_state);
         *state = NULL;
 
         return NULL;
 }
 
+#ifdef HAVE_SHADOW_H
 static struct passwd *
 entry_generator_cachedir (Daemon       *daemon,
                           GHashTable   *users,
                           GHashTable   *local_users,
                           gpointer     *state,
                           struct spwd **shadow_entry)
+#else
+static struct passwd *
+entry_generator_cachedir (Daemon       *daemon,
+                          GHashTable   *users,
+                          GHashTable   *local_users,
+                          gpointer     *state)
+#endif
 {
         struct passwd *pwent;
 
@@ -376,7 +421,9 @@ entry_generator_cachedir (Daemon       *daemon,
                         errno = 0;
                         pwent = getpwnam (name);
                         if (pwent != NULL) {
+#ifdef HAVE_SHADOW_H
                                 *shadow_entry = getspnam (pwent->pw_name);
+#endif
 
                                 return pwent;
                         } else if (errno == 0) {
@@ -414,12 +461,20 @@ entry_generator_cachedir (Daemon       *daemon,
         return NULL;
 }
 
+#ifdef HAVE_SHADOW_H
 static struct passwd *
 entry_generator_requested_users (Daemon       *daemon,
                                  GHashTable   *users,
                                  GHashTable   *local_users,
                                  gpointer     *state,
                                  struct spwd **shadow_entry)
+#else
+static struct passwd *
+entry_generator_requested_users (Daemon       *daemon,
+                                 GHashTable   *users,
+                                 GHashTable   *local_users,
+                                 gpointer     *state)
+#endif
 {
         DaemonPrivate *priv = daemon_get_instance_private (daemon);
         struct passwd *pwent;
@@ -447,7 +502,9 @@ entry_generator_requested_users (Daemon       *daemon,
                                 if (pwent == NULL) {
                                         g_debug ("user '%s' requested previously but not present on system", name);
                                 } else {
+#ifdef HAVE_SHADOW_H
                                         *shadow_entry = getspnam (pwent->pw_name);
+#endif
 
                                         return pwent;
                                 }
@@ -471,14 +528,20 @@ load_entries (Daemon            *daemon,
         DaemonPrivate *priv = daemon_get_instance_private (daemon);
         gpointer generator_state = NULL;
         struct passwd *pwent;
+#ifdef HAVE_SHADOW_H
         struct spwd *spent = NULL;
+#endif
         User *user = NULL;
 
         g_assert (entry_generator != NULL);
 
         for (;;) {
+#ifdef HAVE_SHADOW_H
                 spent = NULL;
                 pwent = entry_generator (daemon, users, local_users, &generator_state, &spent);
+#else
+                pwent = entry_generator (daemon, users, local_users, &generator_state);
+#endif
                 if (pwent == NULL)
                         break;
 
@@ -499,7 +562,11 @@ load_entries (Daemon            *daemon,
 
                         /* freeze & update users not already in the new list */
                         g_object_freeze_notify (G_OBJECT (user));
+#ifdef HAVE_SHADOW_H
                         user_update_from_pwent (user, pwent, spent);
+#else
+                        user_update_from_pwent (user, pwent);
+#endif
 
                         g_hash_table_insert (users, g_strdup (user_get_user_name (user)), user);
                         g_debug ("loaded user: %s", user_get_user_name (user));
@@ -976,15 +1043,24 @@ throw_error (GDBusMethodInvocation *context,
 }
 
 static User *
+#ifdef HAVE_SHADOW_H
 add_new_user_for_pwent (Daemon        *daemon,
                         struct passwd *pwent,
                         struct spwd   *spent)
+#else
+add_new_user_for_pwent (Daemon        *daemon,
+                        struct passwd *pwent)
+#endif
 {
         DaemonPrivate *priv = daemon_get_instance_private (daemon);
         User *user;
 
         user = user_new (daemon, pwent->pw_uid);
+#ifdef HAVE_SHADOW_H
         user_update_from_pwent (user, pwent, spent);
+#else
+        user_update_from_pwent (user, pwent);
+#endif
         user_register (user);
 
         g_hash_table_insert (priv->users,
@@ -1013,9 +1089,13 @@ daemon_local_find_user_by_id (Daemon *daemon,
         user = g_hash_table_lookup (priv->users, pwent->pw_name);
 
         if (user == NULL) {
+#ifdef HAVE_SHADOW_H
                 struct spwd *spent;
                 spent = getspnam (pwent->pw_name);
                 user = add_new_user_for_pwent (daemon, pwent, spent);
+#else
+                user = add_new_user_for_pwent (daemon, pwent);
+#endif
 
                 priv->explicitly_requested_users = g_list_append (priv->explicitly_requested_users,
                                                                   g_strdup (pwent->pw_name));
@@ -1041,9 +1121,13 @@ daemon_local_find_user_by_name (Daemon      *daemon,
         user = g_hash_table_lookup (priv->users, pwent->pw_name);
 
         if (user == NULL) {
+#ifdef HAVE_SHADOW_H
                 struct spwd *spent;
                 spent = getspnam (pwent->pw_name);
                 user = add_new_user_for_pwent (daemon, pwent, spent);
+#else
+                user = add_new_user_for_pwent (daemon, pwent);
+#endif
 
                 priv->explicitly_requested_users = g_list_append (priv->explicitly_requested_users,
                                                                   g_strdup (pwent->pw_name));
@@ -1309,7 +1393,11 @@ daemon_create_user_authorized_cb (Daemon              
         User *user;
 
         g_autoptr (GError) error = NULL;
+#ifndef __OpenBSD__
         const gchar *argv[9];
+#else
+        const gchar *argv[11];
+#endif
         g_autofree gchar *admin_groups = NULL;
 
         if (getpwnam (cd->user_name) != NULL) {
@@ -1345,9 +1433,17 @@ daemon_create_user_authorized_cb (Daemon              
 
                 argv[4] = "-G";
                 argv[5] = admin_groups;
+#ifdef __OpenBSD__
+                argv[6] = "-L";
+                argv[7] = "staff";
+                argv[8] = "--";
+                argv[9] = cd->user_name;
+                argv[10] = NULL;
+#else
                 argv[6] = "--";
                 argv[7] = cd->user_name;
                 argv[8] = NULL;
+#endif
         } else if (cd->account_type == ACCOUNT_TYPE_STANDARD) {
                 argv[4] = "--";
                 argv[5] = cd->user_name;
@@ -1527,6 +1623,34 @@ daemon_delete_user_authorized_cb (Daemon              
                 return;
         }
 
+/*
+ * Under OpenBSD there is no /etc/login.defs (for USERGROUPS_ENAB), so
+ * we need to explicitely remove the user's group if it contains no more
+ * members and matches the username.
+ */
+#ifdef __OpenBSD__
+        struct group *grp;
+        GError *grperror;
+        const gchar *grpargv[3];
+
+        grp = getgrnam (pwent->pw_name);
+
+        if ((grp != NULL) && (*grp->gr_name == *pwent->pw_name) && (*grp->gr_mem == NULL)) {
+                sys_log (context, "delete group '%d'", pwent->pw_gid);
+
+                grpargv[0] = "/usr/sbin/groupdel";
+                grpargv[1] = pwent->pw_name;
+                grpargv[2] = NULL;
+
+                grperror = NULL;
+                if (!spawn_sync (grpargv, &grperror)) {
+                    throw_error (context, ERROR_FAILED, "running '%s' failed: %s", grpargv[0], grperror->message);
+                    g_error_free (grperror);
+                    return;
+                }
+        }
+#endif
+
         sys_log (context, "delete user '%s' (%d)", pwent->pw_name, ud->uid);
 
         user = daemon_local_find_user_by_id (daemon, ud->uid);
@@ -1554,11 +1678,18 @@ daemon_delete_user_authorized_cb (Daemon              
 
         argv[0] = "/usr/sbin/userdel";
         if (ud->remove_files) {
+#ifdef __OpenBSD__
+                argv[1] = "-r";
+                argv[2] = "--";
+                argv[3] = pwent->pw_name;
+                argv[4] = NULL;
+#else
                 argv[1] = "-f";
                 argv[2] = "-r";
                 argv[3] = "--";
                 argv[4] = pwent->pw_name;
                 argv[5] = NULL;
+#endif
         } else {
                 argv[1] = "-f";
                 argv[2] = "--";
@@ -1803,9 +1934,8 @@ load_autologin (Daemon   *daemon,
         else if (dm_type == DISPLAY_MANAGER_TYPE_GDM)
                 return load_autologin_gdm (daemon, name, enabled, error);
 
-        g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _ ("Unsupported Display Manager"));
-
-        return FALSE;
+        /* Default to GDM for backward compatibility */
+        return load_autologin_gdm (daemon, name, enabled, error);
 }
 
 static gboolean
@@ -1885,7 +2015,8 @@ save_autologin (Daemon      *daemon,
         else if (dm_type == DISPLAY_MANAGER_TYPE_GDM)
                 return save_autologin_gdm (daemon, name, enabled, error);
 
-        return FALSE;
+        /* Default to GDM for backward compatibility */
+        return save_autologin_gdm (daemon, name, enabled, error);
 }
 
 gboolean
