$OpenBSD: patch-src_user_c,v 1.29 2021/08/30 19:10:43 ajacoutot Exp $

Index: src/user.c
--- src/user.c.orig
+++ src/user.c
@@ -138,9 +138,14 @@ user_reset_icon_file (User *user)
 }
 
 void
+#ifdef HAVE_SHADOW_H
 user_update_from_pwent (User          *user,
                         struct passwd *pwent,
                         struct spwd   *spent)
+#else
+user_update_from_pwent (User          *user,
+                        struct passwd *pwent)
+#endif
 {
         g_autofree gchar *real_name = NULL;
         gboolean is_system_account;
@@ -199,10 +204,24 @@ user_update_from_pwent (User          *user,
         accounts_user_set_shell (ACCOUNTS_USER (user), pwent->pw_shell);
 
         passwd = NULL;
+#ifdef HAVE_SHADOW_H
         if (spent)
                 passwd = spent->sp_pwdp;
+#endif
 
+#ifdef __OpenBSD__
+        struct passwd *pw = getpwnam_shadow (pwent->pw_name);
+        if (pw)
+                passwd = pw->pw_passwd;
+        if (g_strcmp0(passwd, "skey") == 0)
+                passwd = NULL;
+#endif
+
+#ifdef __OpenBSD__
+        if (passwd && passwd[0] == '*') {
+#else
         if (passwd && passwd[0] == '!') {
+#endif
                 locked = TRUE;
         }
         else {
@@ -218,6 +237,7 @@ user_update_from_pwent (User          *user,
                 mode = PASSWORD_MODE_NONE;
         }
 
+#ifdef HAVE_SHADOW_H
         if (spent) {
                 if (spent->sp_lstchg == 0) {
                         mode = PASSWORD_MODE_SET_AT_LOGIN;
@@ -231,6 +251,9 @@ user_update_from_pwent (User          *user,
                 user->days_after_expiration_until_lock = spent->sp_inact;
                 user->account_expiration_policy_known = TRUE;
         }
+#else
+	user->expiration_time = pwent->pw_expire;
+#endif
 
         accounts_user_set_password_mode (ACCOUNTS_USER (user), mode);
         is_system_account = !user_classify_is_human (accounts_user_get_uid (ACCOUNTS_USER (user)),
@@ -1602,7 +1625,11 @@ user_change_locked_authorized_cb (Daemon              
                          accounts_user_get_user_name (ACCOUNTS_USER (user)),
                          accounts_user_get_uid (ACCOUNTS_USER (user)));
                 argv[0] = "/usr/sbin/usermod";
+#ifdef __OpenBSD__
+                argv[1] = locked ? "-Z" : "-U";
+#else
                 argv[1] = locked ? "-L" : "-U";
+#endif
                 argv[2] = "--";
                 argv[3] = accounts_user_get_user_name (ACCOUNTS_USER (user));
                 argv[4] = NULL;
@@ -1671,14 +1698,24 @@ user_change_account_type_authorized_cb (Daemon        
 {
         AccountType account_type = GPOINTER_TO_INT (data);
         g_autoptr(GError) error = NULL;
+#ifndef __OpenBSD__
         gid_t *groups;
+#else
+        gid_t groups[NGROUPS_MAX + 1];
+        struct group *obsdgrp;
+#endif
         gint ngroups;
         g_autoptr(GString) str = NULL;
         g_auto(GStrv) extra_admin_groups = NULL;
         gid_t admin_gid;
         struct group *grp;
         gint i;
+#ifndef __OpenBSD__
         const gchar *argv[6];
+#else
+        const gchar *argv[8];
+        gchar *class = "\0";
+#endif
 
         if (((AccountType) accounts_user_get_account_type (ACCOUNTS_USER (user))) != account_type) {
                 sys_log (context,
@@ -1694,17 +1731,33 @@ user_change_account_type_authorized_cb (Daemon        
                 }
                 admin_gid = grp->gr_gid;
 
+#ifdef __OpenBSD__
+                ngroups = sizeof(groups) / sizeof(gid_t);
+                if (getgrouplist (accounts_user_get_user_name (ACCOUNTS_USER (user)), user->gid, groups, &ngroups) == -1) {
+                        g_warning ("too many groups");
+                        account_type = ACCOUNT_TYPE_STANDARD;
+                }
+#else
                 ngroups = get_user_groups (accounts_user_get_user_name (ACCOUNTS_USER (user)), user->gid, &groups);
+#endif
 
                 str = g_string_new ("");
                 for (i = 0; i < ngroups; i++) {
                         if (groups[i] == admin_gid)
                                 continue;
+#ifdef __OpenBSD__
+                        obsdgrp = getgrgid(groups[i]);
+                        g_string_append_printf (str, "%s,", obsdgrp->gr_name);
+#else
                         g_string_append_printf (str, "%d,", groups[i]);
+#endif
                 }
                 switch (account_type) {
                 case ACCOUNT_TYPE_ADMINISTRATOR:
                         extra_admin_groups = g_strsplit (EXTRA_ADMIN_GROUPS, ",", 0);
+#ifdef __OpenBSD__
+                        class = "staff";
+#endif
 
                         for (i = 0; extra_admin_groups[i] != NULL; i++) {
                                 struct group *extra_group;
@@ -1712,10 +1765,18 @@ user_change_account_type_authorized_cb (Daemon        
                                 if (extra_group == NULL || extra_group->gr_gid == admin_gid)
                                         continue;
 
+#ifdef __OpenBSD__
+                                g_string_append_printf (str, "%s,", extra_group->gr_name);
+#else
                                 g_string_append_printf (str, "%d,", extra_group->gr_gid);
+#endif
                         }
 
+#ifdef __OpenBSD__
+                        g_string_append_printf (str, "%s", ADMIN_GROUP);
+#else
                         g_string_append_printf (str, "%d", admin_gid);
+#endif
                         break;
                 case ACCOUNT_TYPE_STANDARD:
                 default:
@@ -1724,14 +1785,26 @@ user_change_account_type_authorized_cb (Daemon        
                         break;
                 }
 
+#ifndef __OpenBSD__
                 g_free (groups);
+#endif
 
                 argv[0] = "/usr/sbin/usermod";
+#ifdef __OpenBSD__
+                argv[1] = "-S";
+                argv[2] = str->str;
+                argv[3] = "-L";
+                argv[4] = class;
+                argv[5] = "--";
+                argv[4] = accounts_user_get_user_name (ACCOUNTS_USER (user));
+                argv[7] = NULL;
+#else
                 argv[1] = "-G";
                 argv[2] = str->str;
                 argv[3] = "--";
                 argv[4] = accounts_user_get_user_name (ACCOUNTS_USER (user));
                 argv[5] = NULL;
+#endif
 
                 if (!spawn_with_login_uid (context, argv, &error)) {
                         throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message);
