Solved Syntax of the adduser.conf

Hello guys.
First of all: I'm using FreeBSD for a while now since I switched from Linux and I really like the system. But today I had a problem.

I wanted to setup my system in a way, that new users are added to the groups "video" and "operator" by default, when I use the "adduser"-command. Moreover that, they should become a member of the "german" login class.
(For Login class, I followed the instructions in 25.2.1.1. Login Classes Method" of the FreeBSD-Handbook. It works fine!)

So I've setup an "adduser.conf", which looks like this:
Code:
          defaultclass=german
          defaultgroups=operator video
Now, when I try to run "adduser", my system doesn't seem to recognize, my entries in the adduser.conf.
My output - when I try to create an account for "testuser" - looks like this:
Code:
          Username: testuser
          Full Name: Testuser
          Uid (Leave empty for default):
          Login group [testuser]:
          Login group ist testuser. Invite testuser to other groups? []:
          Login class [default]:
          Shell (sh csh tcsh nologin) [sh]:
          ...
When I change my adduser.conf like in the following, it works:
Code:
          defaultclass=german
          defaultgroups=operator
In this case my output looks like this:
Code:
          Username: testuser
          Full Name: Testuser
          Uid (Leave empty for default):
          Login group [testuser]:
          Login group ist testuser. Invite testuser to other groups? [operator]:
          Login class [german]:
          Shell (sh csh tcsh nologin) [sh]:
          ...
So I think, my syntax in the "defaultgroups="-line must be wrong. To find a solution for that, I already looked at the manpage of adduser.conf, but there is no information about the syntax of the "defaultgroups"-entry.


I also didn't find any thread, about that topic and I tried some other entries, but they also didn't work. These are the lines I tried:
Code:
          defaulgroups="operator" "video"
          defaultgroups="operator","video"
          defaultgroups='operator' 'video'
          defaultgroups='operator','video'
          defaultgroups=[operator] [video]
          defaultgroups=[operator],[video]
Does anyone has a solution?



Thank you very much for reading![/video][/video]
 
Just run adduser -C and follow the questions, then look at how /etc/adduser.conf is set up.
 
@ SirDice

Hello, thank you a lot for your reply!
I followed your instructions. The questions of "adduser -C" look like this:
Code:
Uid (Leave empty for default):
Login group []:
Enter additional groups []:
Login class [default]:
...

Now I have the same problem as before.

When I write:
Code:
Uid (Leave empty for default):
Login group []:
Enter additional groups []: operator video
Login class [default]: german

the entry in the adduser.conf looks like before and doesn't work:
Code:
defaultHomePerm=
defaultLgroup=
defaultclass=german
defaultgroups=operator video
...

I also tried to "adduser -C" two times. The first time, I entered:
Code:
Uid (Leave empty for default):
Login group []:
Enter additional groups []: operator
Login class [default]: german
...

The second time, I entered:
Code:
Uid [1002]:
Login group []:
Enter additional groups [operator]: video
Login class [default]: german
...

The only effect was that the the defaultgroup for "operator" was replaced by the defaultgroup for "video". So I still don't add a new user to both groups by default.
Code:
defaultHomePerm=
defaultLgroup=
defaultclass=german
defaultgroups=video
...
 
Code:
Enter additional groups []: operator video

Space delimited should be correct here.
Code:
root@fbsd-test:~ # adduser -C
Uid (Leave empty for default):
Login group []:
Enter additional groups []: wheel operator
Login class [default]:
Shell (sh csh tcsh nologin) [sh]: tcsh
Home directory [/home/]:
Home directory permissions (Leave empty for default):
Use password-based authentication? [yes]:
Use an empty password? (yes/no) [no]:
Use a random password? (yes/no) [no]:
Lock out the account after creation? [no]:
Pass Type  : yes
Class      :
Groups     :  wheel operator
Home       : /home/
Home Mode  :
Shell      : /bin/tcsh
Locked     : no
OK? (yes/no): yes
Re-edit the default configuration? (yes/no): no
Goodbye!
Code:
root@fbsd-test:~ # cat /etc/adduser.conf
# Configuration file for adduser(8).
# NOTE: only *some* variables are saved.
# Last Modified on Thu Oct 12 20:30:23 CEST 2023.

defaultHomePerm=
defaultLgroup=
defaultclass=
defaultgroups=wheel operator
passwdtype=yes
homeprefix=/home
defaultshell=/bin/tcsh
udotdir=/usr/share/skel
msgfile=/etc/adduser.msg
disableflag=
uidstart=1003

Following another adduser:
Code:
root@fbsd-test:~ # adduser
Username: rctest2
Full name: rctest2
Uid [1003]:
Login group [rctest2]:
Login group is rctest2. Invite rctest2 into other groups? []:
Login class [default]:
Shell (sh csh tcsh nologin) [tcsh]:
Home directory [/home/rctest2]:
Additional groups is now empty. Even accepting the default doesn't add the two groups to the userid either. Weird. I think you may have stumbled onto a bug :D
 
/usr/sbin/adduser is a shell script, so it's quite easy to read the actual code.
Code:
[ -n "$ugroups" ] && _grouplist='-G "$ugroups"'
This looks fine. Assuming pw(8) gets used to create the user account:
Code:
     -G grouplist  Set secondary group memberships for an account.  grouplist
                   is a comma, space, or tab-separated list of group names or
                   group numbers.  The user is added to the groups specified
                   in grouplist, and removed from all groups not specified.
                   The current login session is not affected by group
                   membership changes, which only take effect when the user
                   reconnects.  Note: do not add a user to their primary group
                   with grouplist.
So it could be comma, space or tab-separated. But the 'default' of the question shows an empty list ([ ]). I think the error might be somewhere in the code that reads and parses the adduser.conf file.
 
Right. I think the issue might be here:
Code:
input_from_file() {
        _field=

        while read -r fileline ; do
                case "$fileline" in
                \#*|'')
                        ;;
                *)
                        get_user || continue
                        get_gecos
                        get_uid
                        get_logingroup
                        get_class
                        get_shell
                        get_homedir
                        get_homeperm
                        get_password
                        get_expire_dates
                        ugroups="$defaultgroups"

                        add_user
                        ;;
                esac
        done
}
That $defaultgroups variable is empty when the script starts. $default_groups never contains the list from defaultgroups= in adduser.conf.

Then $ugroups gets 'reset' to $defaultgroups:
Code:
get_groups() {
        ugroups="$defaultgroups"
        _input=
        _group=${ulogingroup:-"${username}"}

        if [ -z "$configflag" ]; then
                [ -z "$fflag" ] && echo -n "Login group is $_group. Invite $username"
                [ -z "$fflag" ] && echo -n " into other groups? [$ugroups]: "
        else
                [ -z "$fflag" ] && echo -n "Enter additional groups [$ugroups]: "
        fi
        read _input

        [ -n "$_input" ] && ugroups="$_input"
}

But because $defaultgroups is never read from anywhere but the script itself, it's always empty, thus $ugroups is also always empty by default, unless the interactive script (or a command line option) sets it.

Edit: That might not be entirely correct. Somewhere defaultgroups= is read because it does work if there's only one group. Some more digging is required.
 
The error seems to be in the generated output adduser.conf of adduser -C
Manually editing adduser.conf as follows:
Code:
defaultgroups="wheel video"
akin to kld_list in /etc/rc.conf
After invoking adduser on my 12.4-RELEASE, pw confirms:
Code:
 # pw usershow -n ttt -P                                          pts/0
Login Name: ttt               #1009         Group: ttt               #1010
 Full Name: p ttt
      Home: /home/ttt                       Class:
     Shell: /bin/tcsh                      Office: [None]
Work Phone: [None]                     Home Phone: [None]
Acc Expire: [None]                     Pwd Expire: [None]
    Groups: wheel,video
 
defaultgroups="operator video"

Thank you - that solves the problem ?
When I run "adduser"-command now, the user is by default in both groups.

$id testuser
uid=1002(testuser) gid=1002(testuser) groups=1002(testuser),5(operator),44(video)
 
The error seems to be in the generated output adduser.conf of adduser -C
Right. It really needs some quotes there.
Code:
save_config() {
        echo "# Configuration file for adduser(8)."     >  ${ADDUSERCONF}
        echo "# NOTE: only *some* variables are saved." >> ${ADDUSERCONF}
        echo "# Last Modified on `${DATECMD}`."         >> ${ADDUSERCONF}
        echo ''                         >> ${ADDUSERCONF}
        echo "defaultHomePerm=$uhomeperm" >> ${ADDUSERCONF}
        echo "defaultLgroup=$ulogingroup" >> ${ADDUSERCONF}
        echo "defaultclass=$uclass"     >> ${ADDUSERCONF}
        echo "defaultgroups=$ugroups"   >> ${ADDUSERCONF}
        echo "passwdtype=$passwdtype"   >> ${ADDUSERCONF}
        echo "homeprefix=$homeprefix"   >> ${ADDUSERCONF}
        echo "defaultshell=$ushell"     >> ${ADDUSERCONF}
        echo "udotdir=$udotdir"         >> ${ADDUSERCONF}
        echo "msgfile=$msgfile"         >> ${ADDUSERCONF}
        echo "disableflag=$disableflag" >> ${ADDUSERCONF}
        echo "uidstart=$uidstart"       >> ${ADDUSERCONF}
}
$ugroups needs some quotes around it.
 
Now I also get why it fails, and does so silently.
Code:
if [ -n "$readconfig" ]; then
        # On a long-lived system, the first time this script is run it
        # will barf upon reading the configuration file for its perl predecessor.
        if ( . ${ADDUSERCONF} > /dev/null 2>&1 ); then
                [ -r ${ADDUSERCONF} ] && . ${ADDUSERCONF} > /dev/null 2>&1
        fi
fi
File isn't even parsed. Well, not parsed by the script at least. It's treated as a shell script and sourced. Shell defaultgroups=foo bar results in an error ('bar' command not found). And the error is redirected to /dev/null. It also hints at the origins of the adduser(8) script. It used to be a perl script (back when perl was included with the base) and I'm pretty sure the perl script did some actual parsing, defaultgroups=foo bar would have been perfectly fine in the config.
 
I wanted to setup my system in a way, that new users are added to the groups "video" and "operator" by default, when I use the "adduser"-command.
Not really the default way you intended I think, but you might also have tried the option below without success or may want to use it in the future. According to adduser(8) one can also use:
adduser -G <Space-separated list of additional groups>

Note that you should use quotes for two or more groups as well:
adduser -G "video operator"

Quotes are not needed here:
adduser -G video

Not working:
adduser -G video operator
The adduser sh script uses the "shift" operation in a way that, after processing the -G option, only one string is processed; so, the first argument video is processed, the argument operator after that is not processed.
 
Right. It really needs some quotes there.
Code:
save_config() {
        echo "# Configuration file for adduser(8)."     >  ${ADDUSERCONF}
        echo "# NOTE: only *some* variables are saved." >> ${ADDUSERCONF}
        echo "# Last Modified on `${DATECMD}`."         >> ${ADDUSERCONF}
        echo ''                         >> ${ADDUSERCONF}
        echo "defaultHomePerm=$uhomeperm" >> ${ADDUSERCONF}
        echo "defaultLgroup=$ulogingroup" >> ${ADDUSERCONF}
        echo "defaultclass=$uclass"     >> ${ADDUSERCONF}
        echo "defaultgroups=$ugroups"   >> ${ADDUSERCONF}
        echo "passwdtype=$passwdtype"   >> ${ADDUSERCONF}
        echo "homeprefix=$homeprefix"   >> ${ADDUSERCONF}
        echo "defaultshell=$ushell"     >> ${ADDUSERCONF}
        echo "udotdir=$udotdir"         >> ${ADDUSERCONF}
        echo "msgfile=$msgfile"         >> ${ADDUSERCONF}
        echo "disableflag=$disableflag" >> ${ADDUSERCONF}
        echo "uidstart=$uidstart"       >> ${ADDUSERCONF}
}
uicode]$ugroups[/icode] needs some quotes around it.
what about a here document
Code:
save_config() {
        cat > ${ADDUSERCONF} <<EOF
# Configuration file for adduser(8)."
# NOTE: only *some* variables are saved."
# Last Modified on `${DATECMD}`."

defaultHomePerm=$uhomeperm"
defaultLgroup=$ulogingroup"
defaultclass=$uclass"
defaultgroups=$ugroups"
passwdtype=$passwdtype"
homeprefix=$homeprefix"
defaultshell=$ushell"
udotdir=$udotdir"
msgfile=$msgfile"
disableflag=$disableflag"
uidstart=$uidstart"
EOF
}
 
Back
Top