How to Build a Multiuser Puppy

How to do things, solutions, recipes, tutorials
Post Reply
Message
Author
User avatar
Pizzasgood
Posts: 6183
Joined: Wed 04 May 2005, 20:28
Location: Knoxville, TN, USA

How to Build a Multiuser Puppy

#1 Post by Pizzasgood »

How To Make a Multiuser Puppy

This guide is based off the work I did to produce Multiuser Puppy, and the discussions we had here and here. I am assuming the reader is comfortable with Puppy's internals and with utilities such as grep, sed, and diff. I will reference the following files: The following packages are also availible for use with shadow-4.1.4.2.pet, Linux-PAM-1.1.0.pet, and sudo-1.7.2p1.pet:


Misc. Small Changes
  • Create an empty directory '/home'.
  • Make /tmp 1777 (sticky and globally writable). The stickiness makes it so that if Alice creates the file /tmp/my_temporary_file, Bob can't modify that file unless Alice sets the permissions to let him. Otherwise he could move or delete the file, which could obviously be a pretty bad thing. The downside is that a user can spam /tmp with a bunch of files that other users might want to create...
  • Make /dev/zero and /dev/ptmx globally writable. The former is needed for a number of programs to run for some reason. The latter is needed by rxvt.
  • Make ddcprobe setuid. The scripts supporting X needed this.
  • Make /usr/X11R7/bin/Xvesa setuid.
  • IceWM's toolbar has some paths within ~/ but it can't handle variables. So I just trimmed off the /root/ part, making them relative. That seems to work. It may have problems if you start icewm from a location other than your home directory however.
  • Upgrade pcursorsel-0.1 to 0.2, which is multiuser-friendly (link)
  • Add a line in /usr/sbin/puppyinstaller that copies /home when it's setting up a full install.
  • The /usr/share/applications/file_sharing.desktop file had an Exec line like this:

    Code: Select all

    Exec=rox -d /root/File-Sharing
    But that obviously won't do. I couldn't get it to work with variables either. So I changed it to this:

    Code: Select all

    Exec=filesharedir
    and then added the script /usr/sbin/filesharedir with the following contents:

    Code: Select all

    #!/bin/sh
    exec rox -d ${HOME}/File-Sharing



Xlock and box_splash (from pwidgets and ptray)

These use some GTK dialog stuff that had absolute paths into /root/. Changing them is pretty easy, but you have to be careful about the quotes. Here are the diffs:

/usr/local/apps/Xlock/AppRun:

Code: Select all

- puppy-unleashed/packages/xlockmore-5.20.1patched/usr/local/apps/Xlock/AppRun -
index e7fc9b3..77f102c 100755
@@ -23,11 +23,11 @@ if [ "$PARAM1" = "-password" ];then
   <vbox>
    <text><label>"The first time Xlock runs, it will ask for a key, meaning a
 password. To change the password, you need to delete the
-file /root/.xlockrc, which is all that this button does..."</label>
+file '"${HOME}/.xlockrc"', which is all that this button does..."</label>
    </text>
    <button>
     <label>Click to clear password</label>
-    <action>rm -f /root/.xlockrc</action>
+    <action>rm -f ${HOME}/.xlockrc</action>
     <action>exit:PASSWD</action>
    </button>
   </vbox>
@@ -196,7 +196,7 @@ if [ ! "`echo "$PARAM1" | grep --extended-regexp "configure|inroot"`" = "" ];the
 fi
 
 
-if [ ! -f /root/.xlockrc ];then
+if [ ! -f ${HOME}/.xlockrc ];then
  XLOCKPARAMS="`cat /etc/xlockscreenparams`"
  rxvt -bg orange -g 36x1 -title "Create key (password)" -e xlock $XLOCKPARAMS
 else
/usr/local/pwidgets/box_splash:

Code: Select all

---- puppy-unleashed/packages/pwidgets-2.0.8/usr/local/pwidgets/box_splash ----
index d6a57e8..ea4d39f 100755
@@ -5,10 +5,10 @@ export pwidgets_splash='
  <frame>
   <text><label>""</label></text>
   <text use-markup="true"><label>"<b>Pwidgets</b>"</label></text>
-  <text><input file>/root/.pwidgets/tmp/pwidgets-splashtext</input></text>
+  <text><input file>'"${HOME}/.pwidgets/tmp/pwidgets-splashtext"'</input></text>
   <progressbar>
    <label>Sigmund Berglund,   GPL 2008,2009</label>
-   <input>while [ "$I" != "100" ]; do I=`cat /root/.pwidgets/tmp/pwidgets-splash`; echo $I; usleep 500000; done</input>
+   <input>while [ "$I" != "100" ]; do I=`cat ${HOME}/.pwidgets/tmp/pwidgets-splash`; echo $I; usleep 500000; done</input>
    <action type="exit">Ready</action>
   </progressbar>
  </frame>
/usr/local/ptray/box_splash:

Code: Select all

-------- puppy-unleashed/packages/ptray-0.5/usr/local/ptray/box_splash --------
index bbe07ac..171950b 100755
@@ -4,10 +4,10 @@ export ptray_splash='
 <vbox>
  <frame>
   <text><label>""</label></text>
-  <text><input file>/root/.ptray/tmp/ptray-splashtext</input></text>
+  <text><input file>'"${HOME}/.ptray/tmp/ptray-splashtext"'</input></text>
   <progressbar>
    <label>Sigmund Berglund,   GPL 2008,2009</label>
-   <input>while [ "$I" != "100" ]; do I=`cat /root/.ptray/tmp/ptray-splash`; echo $I; usleep 500000; done</input>
+   <input>while [ "$I" != "100" ]; do I=`cat ${HOME}/.ptray/tmp/ptray-splash`; echo $I; usleep 500000; done</input>
    <action type="exit">Ready</action>
   </progressbar>
  </frame>
If you haven't dealt with diffs before, don't worry. In case you haven't already figured it out, the original lines are the ones with a - in front, and the new ones are the ones with a +. That entire first column is extra, by the way. You'll note that the "<vbox>" tag is starting one space away from the edge. In reality it starts immediately on the edge.




Add more virtual terminals (optional, but makes life easier).

This one is pretty simple. You just have to edit /etc/inittab and add more lines, incrementing the tty numbers. For example, to go from two to six, you change:

Code: Select all

::sysinit:/etc/rc.d/rc.sysinit
tty1::respawn:/sbin/getty -n -l /bin/autologinroot 38400 tty1
tty2::respawn:/sbin/getty 38400 tty2
::ctrlaltdel:/sbin/reboot
to

Code: Select all

::sysinit:/etc/rc.d/rc.sysinit
tty1::respawn:/sbin/getty -n -l /bin/autologinroot 38400 tty1
tty2::respawn:/sbin/getty 38400 tty2
tty3::respawn:/sbin/getty 38400 tty3
tty4::respawn:/sbin/getty 38400 tty4
tty5::respawn:/sbin/getty 38400 tty5
tty6::respawn:/sbin/getty 38400 tty6
::ctrlaltdel:/sbin/reboot
Note: This will result in X running on VT 7 rather than VT 3.

If you have implemented toggleable autologin as described below, be sure to edit the /etc/inittab-AUTO and /etc/inittab-NOAUTO files too.




Set Puppy up to be able to optionally stop booting at a login prompt. (Included within user_utils-0.1.pet)

Make two copies of /etc/inittab, one named inittab-AUTO and one named inittab-NOAUTO. In the NOAUTO one, edit the tty1 line to look more like the others. As in, rather than

Code: Select all

tty1::respawn:/sbin/getty -n -l /bin/autologinroot 38400 tty1
use

Code: Select all

tty1::respawn:/sbin/getty 38400 tty1
Next, you just need to add a wizard to copy one or the other over inittab. I included such a wizard in the user_utils-0.1.pet package, named /usr/sbin/autologin-wizard.

You could also do this without the AUTO and NOAUTO versions by using sed to edit the tty1 line. However, if the user wanted to change the structure of the file, they'd have to modify the script too. This way they just have to modify the other two inittab-* files.




Proper user utilities such as useradd and gpasswd (shadow-4.1.4.2.pet)

Puppy includes limited versions of the real tools courtisy of Busybox. They don't have as many features and aren't as nice. So you'll need to replace them with the real thing. They are in a package called Shadow and I've provided a package above. I made a few changes from the default configuration, as follows:

Code: Select all

./configure --build=i486-t2-linux-gnu --prefix=/
/etc/login.defs:
  • Prevent it from telling the user he has no mail after every login.
    • Change MAIL_CHECK_ENAB from yes to no
    Use md5 for the password hash, which removes the 8 char max limit.
    • Add ENCRYPT_METHOD MD5
    Put /sbin and /usr/sbin into the PATH for limited users
    • Change ENV_PATH from PATH=/bin:/usr/bin to PATH=/sbin:/bin:/usr/sbin:/usr/bin
Note that the following binaries should be SETUID (chmod u+s <filenames>) if the aren't already:
  • /bin/su
    /bin/chage
    /bin/chfn
    /bin/chsh
    /bin/expiry
    /bin/gpasswd
    /bin/newgrp
    /bin/passwd
If you are using Unleashed, be sure you deal with any potential overlap from the busybox versions. I did this by duplicating the busybox package to create a new one with "-no_shadow_overlap" appended to the version number, and then removing the following files from it (and updating packages.txt appropriately to load this rather than the old busybox package):
  • /bin/addgroup
    /bin/adduser
    /bin/delgroup
    /bin/deluser
    /bin/login
    /bin/su
    /usr/bin/passwd
You may want to go into the shadow package and add symlinks from useradd etc. to adduser. I didn't do this because it's easier for me to remember which versions of the utilities I'm working with if I have to use the real name.




/etc/skel

It's nice to have a template to create users' home directories from. That template is generally /etc/skel. When you use the useradd program with the -m option, it will automatically create the user's home directory and populate it from /etc/skel. But where is /etc/skel populated from? I'm a lazy person, so I decided to populate /etc/skel from /root, and to not bother being picky about only copying specific files. Of course, some things will need adjusting so that their paths work out right. Sometimes you'll have relative symlinks that point from /root/the_link to ../usr/bin/wherever_the_target_is. That link would no longer work if it started in /home/alice/. And sometimes a link named /root/link_name will be an absolute link pointing at /root/link_target, which wouldn't break when moved to /home/alice/, but it wouldn't help much either. And obviously, some files will have '/root/' specified in them. So, I wrote a script that will automatically take care of all that:

Code: Select all

usage: populate_skel [-u|-c|-n|-e] [-s SOURCE_DIR ] [ -d DEST_DIR ]

This is a script to populate the /etc/skel directory from the
/root directory, which attempts to also correct any absolute
symlinks pointing into /root and any relative symlinks pointing
out of /root, so those would break during the move.  It also
uses sed to convert instances of "/root/" to "${HOME}/" in the
files copied.

 -u             Only copy newer files
 -c             Delete DEST_DIR before the copy
 -n             Do not attempt to correct symlinks
 -e             Do no change instances of "/root/" to "${HOME}/"
 -s SOURCE_DIR  Specify a different source than /root
 -d DEST_DIR    Specify a different destination than /etc/skel
This isn't perfect. Some files cannot handle a "${HOME}" inside them. And some files might be corrupted if you try using this (for example, you should generally delete any seamonkey profile that gets copied into /etc/skel with this).

The script is included in the user_utils-0.1.pet package.

I also modified my createpuppy script from Unleashed to run populate_skel. That way I don't need to mess with modifying all the packages to put things in /etc/skel. I just let them populate /root normally, then createpuppy will run populate_skel -n. I don't remember why I had it use the -n option, but I'm sure there was a good reason for that... I also added a line to clear out the mozilla profile after populate_skel finishes. Here is the diff:

Code: Select all

diff --git a/puppy-unleashed/createpuppy b/puppy-unleashed/createpuppy
index 0b5d20b..d8429b2 100755
--- a/puppy-unleashed/createpuppy
+++ b/puppy-unleashed/createpuppy
@@ -17,6 +17,7 @@
 #v406 kernels/<sub dir> name can now be named <kern version>-<text>
 #v411 remove stray unipup scripts.
 #v412 add ssb.ko module to initrd (needed by ohci-hcd.ko).
+#vPP4 add option to create /etc/skel based on /root
 
 APATTERN='^".\+" ".\+" .\+ ".*" \\'
 ERRPKG="`cat packages.txt | grep -v "$APATTERN"`"
@@ -815,6 +816,19 @@ sync
 cp -f /tmp/PuppyPinfixed rootfs-complete/root/Choices/ROX-Filer/PuppyPin
 
 
+#To support multiuser, create /etc/skel from /root
+if [ -x rootfs-complete/usr/sbin/populate_skel ]; then
+ echo "Press ENTER to create /etc/skel from /root using 'populate_skel', or"
+ echo "any printable character and then ENTER to not create /etc/skel: "
+ read CREATE_SKEL
+ if [ "$CREATE_SKEL" = "" ]; then
+  rootfs-complete/usr/sbin/populate_skel -n -s rootfs-complete/root -d rootfs-complete/etc/skel
+  #the populate script seems to corrupt the mozilla profile, so clear that out
+  rm -r rootfs-complete/etc/skel/.mozilla
+  echo
+ fi
+fi
+
 echo -n "Press ENTER to build files that will be in the iso: "
 read yabbo
 echo
Some of the files that need to have a direct path rather than ${HOME} are ~/.gtkrc*, ~/.jwmrc*, and ~/.jwm/*. So for ~/.gtkrc* I added the following code in ~/.xinitrc:

Code: Select all

#make sure the gtk files have the home directory rather than ${HOME}, as they can't handle that
for i in $HOME/.gtkrc*; do sed -i "s|\\\${HOME}|$HOME|g" "$i"; done
For the JWM files, I moved the jwm binary from /usr/X11R7/bin/jwm to /usr/X11R7/bin/jwm.bin, and then created /usr/X11R7/bin/jwm as a shell script containing the following:

Code: Select all

#!/bin/sh
find "$HOME" -name '.jwm*' -type f -exec sed -i "s|\\\${HOME}|$HOME|g" "{}" \+
find "$HOME/.jwm" -type f -exec sed -i "s|\\\${HOME}|$HOME|g" "{}" \+
exec jwm.bin "$@"
Those changes are not included in the user_utils package.

During this guide I will often say that I did something in /etc/skel/ or ~/. Technically I did those things in /root and the populate_skel script propagated the changes into /etc/skel for me. Meaning that those changes also apply to /root, not only /etc/skel. Something to be aware of.




Configuring bashrc

A confusing point is that Bash doesn't support a global bashrc, but many sites refer to /etc/bashrc as being global. How it actually works is that you set up the default ~/.bashrc file to include the "global" /etc/bashrc file at the top. The user of course can edit his own .bashrc file if he wants, eliminating that inclusion. But this way if he leaves it and you later decide to change something in /etc/bashrc, all users who still include that from their .bashrc files will automatically inherit the changes. If you had instead just defined those defaults in the /etc/skel/.bashrc file, you would have to look though and maybe modify every user's .bashrc, which isn't desirable for many reasons (privacy, laziness, etc.)

So, in the /etc/skel/.bashrc file, you'll want to add something like this up near the top:

Code: Select all

#source the global bashrc file
[ -f /etc/bashrc ] && . /etc/bashrc
As you can see, that code will be perfectly happy even if /etc/bashrc doesn't actually exist.

For Multiuser Puppy, I also removed the sourcing of /etc/profile from the /etc/skel/.bashrc file, so that the above is the only code actually being run (I did leave some commented out stuff).

As for what to put into /etc/bashrc, that would be things like aliases and what not. In a default Puppy, ~/.bashrc sources /etc/profile, but it mostly doesn't need to. The main thing you gain from that is the aliases defined there. Well, we can just move them out into /etc/bashrc.

The following is the contents of my /etc/bashrc:

Code: Select all

#global bashrc file
#(actually, it must be sourced in each user's ~/.bashrc, but whatever)

#Allow limited users to set their timezone with the ~/Choices/localtime file
[ "$USER" != "root" ] && [ -e ${HOME}/Choices/localtime ] && export TZ=$(cat ${HOME}/Choices/localtime)

#use color in ls if o/p to a tty, not in a script...
alias ls='ls --color=auto'
#add some common ls aliases
alias ll='ls -l'
alias la='ls -a'
alias lA='ls -A'
alias lal='ls -al'

#v4.00 run e3vi whenever vi excuted...
alias vi=e3vi
I also removed the alias vi=e3vi and alias ls='ls --color=auto' lines from /etc/profile.

You may also want to add alias grep='grep --color=auto' to /etc/bashrc. I do that on my personal systems, but I left it out of this one because some people take offense to colored grepping. You'll note that I did add some ls aliases though. I figured they wouldn't bother anybody. And people can always override them in their ~/.bashrc file.

I'll explain the code about the timezone in the next section.

One last thing you should probably do is to create a symlink named /etc/skel/.profile pointed at .bashrc. I don't recall off the top of my head which one gets run under which circumstances, but this helps it remain more consistent if you log in under SSH.




Add sudo (Linux-PAM-1.1.0.pet, sudo-1.7.2p1.pet)

Sudo is useful in that you can use it to let individual users run specific commands with root privileges, without giving them the root password or letting them be able to run any arbitrary command as root (though if you make them a member of the "wheel" group, that does happen). Sudo depends on PAM support, so first you need to install Linux-PAM-1.1.0.pet. Then you can install sudo-1.7.2p1.pet. Sudo is configured by the files /etc/pam.d/sudo and /etc/sudoers. The former tells PAM what kinds of authentication need to happen for a user to use sudo. The file I included in the above package just requires the user to enter his password (not the root password). The latter file, /etc/sudoers, defines who is allowed to run what, along with some options for sudo. To edit it, use the visudo command. I created the "wheel" group and uncommented the option in /etc/sudoers that lets member of "wheel" run any command. I also set the default editor to be mp, but you can change it to geany or whatever you want by finding the line that looks like this:

Code: Select all

Defaults editor=/usr/local/bin/mp
and changing it to this:

Code: Select all

Defaults editor=/usr/bin/geany
I'm not going to get into how to configure sudo. I will mention however that in general, it's better to explicitely allow a user to run a limited selection of programs with it, rather than placing the user into the 'wheel' group so that he can run anything.

Note that /usr/bin/sudo must be setuid, and /etc/sudoers must be chmod 0440.

The sources for these packages are here: Linux-PAM, Sudo.




Let users use the GUI timezone wizard to set their timezone

Anybody can set their timezone simply be specifying the TZ variable in ~/.bashrc. But to make things more GUI-friendly, you can modify the /usr/sbing/timezone-set script to detect if the user is not root, and if so, create a file named ~/Choices/localtime that contains the timezone (the path to the file in /usr/share/zoneinfo for the timezone in question). An example timezone-set script is provided in timezone-set.tar.gz.
Next add a couple lines in /etc/bashrc to check for the existance of that file, and if found set the TZ variable accordingly. The lines to add to /etc/bashrc are these:

Code: Select all

#Allow limited users to set their timezone with the ~/Choices/localtime file
[ "$USER" != "root" ] && [ -e ${HOME}/Choices/localtime ] && export TZ=$(cat ${HOME}/Choices/localtime)
As you can see, tihs doesn't allow root to use this system. The root user will get and set the system's default time. This is for consistency with the stock Puppy.

Note: That code is also shown up above in the bashrc section, so don't add it twice...




Making the Prompt More Informative

Some people like long prompts that tell them the date and their location in the filesystem and who they are and whether it's sunny out and all kinds of other nonsense. I'm not going to get into all that. Since I'm trying to make this essentially look and work like a stock Puppy with minimal changes to become multiuser friendly, I opted to only make a very small change to the prompt. The prompt is controlled by the PS1 variable, which is set in /etc/profile. I changed it from being a hardcoded # to using \$, which causes it to show # only when you are root, otherwise it shows a $:

Code: Select all

PS1='\$ '
Note: Stock Puppy quotes the prompt with normal double-quotes. If you want to use \$, you must use single quotes. Otherwise you have to add one or two extra backslashes to get everything properly escaped.

It's also possible to set the prompt to be a different color. I generally set mine to be red if I'm root, and yellow or green otherwise. It's easier to distinguish the difference in color than the difference between # and $, IMHO. Also, it makes the prompt stand out from the rest of the text better, and generally just looks nicer. Again, because I'm trying to keep things as close to stock as possible, I did not do that here.

If you're interested in making things fancy, read this.




Mounting (mount-stuff.tar.gz)

If you do nothing, only root will be able to mount drives. Depending on how you want to use Puppy, that may be the desired behavior. For most desktop users however, it is not. They'll want to be able to mount their USB drives and what-not without su-ing to root. But opening the system to let any user mount is a Bad Idea, as some server programs will run as their own limited user to minimize the damage should they be compromised. So, what to do? This is where the concept of "groups" kicks in. You can set the "group" option in /etc/fstab for a partition, and then any member of the group that owns the partition will be able to mount it. So first things first: add a "disk" group:

Code: Select all

groupadd disk
Then, you need to chgrp disk all the device nodes in /dev that correspond to drives. /dev/fd*, /dev/s[dr]*, /dev/hd*, and probably some others. There's a good possibility of missing some, but you don't need to worry about that as I'll mention shortly.

Next there needs to be an entry in /etc/fstab for every partition. That's where things get ugly. The sysadmin could of course add them manually, but that's a pain, and doesn't account for when Bob plugs in his USB drive. So, I wrote some scripts that latch into either Barry's "pup_event" system or udev, whichever is being used, and run another script (/sbin/pup_event_backend_fstab) when a new drive is detected. pup_event_backend_fstab then adds an entry to /etc/fstab. Since pup_event and udev run as root, the script will have enough permission to do this. While it's at it, it also makes sure that the device file belongs to the disk group. And to take care of any drives that are already connected on boot, I added some code to /etc/rc.d/rc.sysinit to run pup_event_backend_fstab on the existing drives too. Since in some situations a drive may have a different partition type than the last time it was used (two different USB drives for example) I made sure it's capible of editing lines. I also set it up so that if you manually change an fstab entry to remove the "group" option, the script will not touch that entry anymore. In case you want to have a root-only drive.

The partitions need to be mounted with mount-FULL, not the busybox mount, so I added some code to the mount script that takes care of this automatically, so the user can still use plain old "mount". Also, since a limited user cannot supply his own options, I added some lines to have it detect when just passing the raw commandline to mount-FULL fails and try to send it only the mountpoint. That allows things like Pmount to work with for limited users without actually being modified itself.

For the desktop icons to be updated, I needed to adjust /etc/rc.d/functions4puppy4, /sbin/pup_event_frontend_d, and /sbin/clean_desk_icons to be multiuser friendly. I didn't make pup_event_frontend_d completely multiuser friendly - it has functions involving saving USB installs and such that need to be done as root. But it's good enough to set up the desktop icons.

The modified files are availible in the mount-stuff.tar.gz file.

One catch is that NTFS partitions require mounting with ntfs-3g, but that doesn't work properly with the "group" option in /etc/fstab, and I couldn't get it to be user-friendly. So I added an extra option to the umount-client and umount-daemon (described below) to allow a limited user who is a member of the group owning the device node to tell the daemon to mount the partition (the daemon runs as root). The mount script has been modified to handle this automatically.

So, that takes care of mounting for any user who is a member of the 'disk' group.




Unmounting (mount-stuff.tar.gz)

If you set up mounting as described above, all seems fine and dandy. Until you try to unmount the partition. The "group" option doesn't let users unmount a partition. Probably because there's a chance that another user is now poking around in the partition. Anyway, we want to be able to unmount things so we can remove our USB drives.

So, I wrote /etc/init.d/umount-daemon, which runs as root and monitors /tmp/.umount-requests/. To unmount a partition, I added some code to the umount script that will call the /bin/umount-client script I wrote. umount-client will create a file in /tmp/.umount-request/ with a random name and which contains the path to the mountpoint of the partition. umount-daemon will detect the creation of the file, read the contents, determine if the user is authorized to unmount the partition (check that the group option is set in fstab and that the user and device node have the same group), unmount the partition, and delete the file umount-client created. Then umount-client will return you to the prompt. As mentioned above, it also can be used to mount partitions as root when you are actually a limited user, but that feature is strongly discrouaged. It is only included for rare situations where a limited user simply cannot mount the partition properly, such as with NTFS partitions.

The files needed are included in the mount-stuff.tar.gz file along with the ones for mounting.

So, the user should now be able to mount and unmount his drives with the normal mount and unmount commands, pmount, and the desktop icons. And since they'll all have proper /etc/fstab entries, you can even go into /mnt/ and click the mountpoints to mount them (ROX-Filer handles this automatically).




Audio

Initially, some audio devices in Puppy are globally usable, and some are not. This is not very nice. So, what you can do is make them all 660, and then set their group to "audio" (after creating the audio group of course...). Then, any user who belongs to the audio group can use the audio devices. I used the following commands:

Code: Select all

#create the audio group
groupadd audio
cd /
#have the "audio" group own the audio devices
chgrp audio ./dev/snd/* ./dev/audio ./dev/admmidi ./dev/adsp ./dev/aloadC0 ./dev/amidi ./dev/amixer ./dev/audio ./dev/audio0 ./dev/dmmidi ./dev/dsp ./dev/midi ./dev/mixer ./dev/music ./dev/seq ./dev/sequencer ./dev/sequencer2 ./dev/sndstat ./dev/speaker
#make sure only authorized users can do audio things
chmod 660 ./dev/snd/* ./dev/audio ./dev/admmidi ./dev/adsp ./dev/aloadC0 ./dev/amidi ./dev/amixer ./dev/audio ./dev/audio0 ./dev/dmmidi ./dev/dsp ./dev/midi ./dev/mixer ./dev/music ./dev/seq ./dev/sequencer ./dev/sequencer2 ./dev/sndstat ./dev/speaker



Poweroff and Reboot (power-stuff.tar.gz)

In the stock Puppy, a limited user cannot poweroff or reboot the machine. As with mounting and audio, this may or may not be desireable. Thus, the solution is to add a "power" group and put people who should be able to do such actions into it. Then chmod 750 the poweroff and reboot commands. That's enough to limit who can run the commands to the right people, but it still doesn't grant them the permission to actually do the deed. So I wrote a daemon named /etc/init.d/power-daemon, which is very similar to the umount-daemon. It monitors /tmp/.power-requests/ for files containing "poweroff" or "reboot". The /tmp/.power-requests/ directory has it's permissions set to 770 and is owned by the power group, so only authorized users can create such files. The actual file creation is handled by the poweroff and reboot scripts. When run by non-root users, they create a file with the appropriate contents in /tmp/.power-requests/, which then runs the command again as root. When they are run as root, they skip the /tmp/.power-requests stuff and do what they normally do - run /etc/rc.d/rc.shutdown and then poweroff or reboot the computer.




Adding Users (included in user_utils-0.1.pet)

To avoid the need to remember all these groups when creating a new user, I wrote the /usr/sbin/adduser-wizard script. It gives you a GUI way to createa user, select whether he should be a part of the disk, audio, power, and wheel groups, and lets you set his password. It also uses the -m option when running useradd, so that the user gets his home directory created as well. After the home directory is created, it goes ahead and chmods it to 750 to keep it private. Finally, it goes ahead and adds the /etc/X11/$USER/ directory and sets the ownership to the new user. This wizard is a part of the user_utils-0.1.pet package I made.




Changing the Password (included in user_utils-0.1.pet)

I tried to make a gui for setting your password, but passwd doesn't have a way to accept a password from STDIN or environment variables. There is a program included in shadow called chpasswd that lets you do this, but it only works for root (that's the method I used for the adduser-wizard). I could do it with an "expect" script, but that would mean adding another dependency... So instead, I just wrote a script that pops up an rxvt window and runs the passwd command inside it. This way it can at least be run from the menu. I named it passwd-wizard and included it in the user_utils-0.1.pet.




Pwidgets background

Pwidgets was storing the background in /usr/share/backgrounds/Pwidgets_background, which is root only. So you can get around that by editing /usr/local/pwidgets/func and /usr/sbin/fixwidgets to store it at $HOME/.pwidgets/Pwidgets_background instead. That's in addition to replacing instances of /root/ with $HOME of course.




PetGet

Installing software is something that must be done as root. So added a couple lines near the top to throw an error message if you are not root:

Code: Select all

#Don't bother attempting to run unless root
if [ "$(whoami)" != "root" ]; then
 [ "$(ps -eo comm | grep ^X)" = "X" ] && Xdialog -title "PETget package manager" --msgbox "Sorry, but only the root user\nhas permission to run petget" 0 0
 echo "ERROR: Must be root to run petget" >&2
 exit 1
fi



Fixmenus

This can be made mostly multiuser friendly with just a couple changes to convert /root into ${HOME}

Code: Select all

diff --git a/puppy-unleashed/packages/xdg_puppy-0.7.6-5_4.2/usr/sbin/fixmenus b/puppy-unleashed/packages/xdg_puppy-0.7.6-5_4.2/usr/sbin/fixmenus
index 2dde04b..5eb8038 100755
--- a/puppy-unleashed/packages/xdg_puppy-0.7.6-5_4.2/usr/sbin/fixmenus
+++ b/puppy-unleashed/packages/xdg_puppy-0.7.6-5_4.2/usr/sbin/fixmenus
@@ -7,6 +7,8 @@
 #...the '_' will be converted to a '/', so the generated JWM config file is:
 # /root/.jwmrc
 # 5jan2008: fbpanel,lxpanel support developed by plinej.
+#06Sept2009 PG: Don't bother attempting to run unless root
+#31Oct2009 PG: Allow running as non-root
 
 
 #Puppy 2.14: XDG menu 
@@ -15,7 +17,7 @@ TEMPLATES="`ls -1 /etc/xdg/templates | tr '\n' ' '`"
 for ONETPL in $TEMPLATES
 do
  [ "$ONETPL" = "README.txt" ] && continue
- ONEDEST="`echo -n "$ONETPL" | sed -e 's/_/\//g'`"
+ ONEDEST="`echo -n "$ONETPL" | sed -e 's|_|/|g' -e "s|^/root/|$HOME/|"`"
  ONESRC="/etc/xdg/templates/$ONETPL"
  echo "Generating $ONEDEST..."
  
@@ -24,6 +26,7 @@ do
  cat $ONESRC |
  while read ONELINE
  do
+  ONELINE="`echo -n "$ONELINE" | sed "s%\([='\\\"> ]\+\)/root/%\1$HOME/%g"`"
   EXECMENU="`echo -n "$ONELINE" | grep -o 'PUPPYMENU.*' | cut -f 2-5 -d ' '`"
   if [ "$EXECMENU" = "" ];then
    echo "$ONELINE" >> $ONEDEST
This won't let limited users define their own .desktop files or define their own templates (unless Puppy's XDG system already has support for that and I just don't realize it), but it will let them update their menu entries to match the .desktop files in /usr/share/applications, in case they get out of sync.




The X Windows System (x-stuff.tar.gz)

Beside the following changes, this also needed the permissions of /dev/zero changed, and ddcprobe and Xvesa setuid as described above.

~/.xinitrc
  • Change all instances of /root/ into $HOME/
    Use ~/Choices/windowmanager rather than /etc/windowmanager
  • Use /tmp/${USER}-<filename> rather than /tmp/<filename> for temporary files.
    /usr/sbin/chooselocale
    • Use ~/Choices/windowmanager rather than /etc/windowmanager
    /usr/sbin/input-wizard
    • If the user is not root, use /etc/X11/$USER/xorg.conf rather than /etc/X11/xorg.conf.
    /usr/sbin/delayedrun
    • Use ${HOME}/Choices/videomode rather than /etc/videomode
    /usr/sbin/framebufferwizard
    • Use ${HOME}/Choices/videomode rather than /etc/videomode
    /usr/sbin/video-wizard
    • Use /tmp/${USER}-<filename> rather than /tmp/<filename> for temporary files.
      Use ${HOME}/Choices/videomode rather than /etc/videomode
    /usr/sbin/xorgwizard (note - xorgwizard doesn't actually work yet for limited users)
    • Change all instances of /root/ into $HOME/
      Use ~/Choices/windowmanager rather than /etc/windowmanager
      Use /tmp/${USER}-<filename> rather than /tmp/<filename> for temporary files.
      If the user is not root, use /etc/X11/$USER/xorg.conf rather than /etc/X11/xorg.conf
      Use ${HOME}/Choices/videomode rather than /etc/videomode
    /etc/windowmanager
    • Moved to ~/Choices/windowmanager
    /usr/X11R7/bin/restartwm
    • Use ~/Choices/windowmanager rather than /etc/windowmanager
      Use /tmp/${USER}-<filename> rather than /tmp/<filename> for temporary files.
    /usr/X11R7/bin/wmpoweroff
    • Use /tmp/${USER}-<filename> rather than /tmp/<filename> for temporary files.
    /usr/X11R7/bin/wmreboot
    • Use /tmp/${USER}-<filename> rather than /tmp/<filename> for temporary files.
    /usr/X11R7/bin/xwin
    • Change all instances of /root/ into $HOME/
      Use /tmp/XLOADED instead of /etc/.XLOADED
      Make /tmp/XLOADED world-writable (rather than doing it per-user, because you don't want Alice starting X if Bob is already running it!)
      Use /tmp/${USER}-<filename> rather than /tmp/<filename> for temporary files.
      Use ${HOME}/Choices/windowmanager rather than /etc/windowmanager
      Use /etc/X11/$USER/xorg.conf if it exists, otherwise use /etc/X11/xorg.conf as usual.
      Use ${HOME}/Choices/videomode rather than /etc/videomode
    The final forms of those are all availible in the x-stuff.tar.gz package.

    Also modified /usr/bin/seahaven-multi to use ${HOME}/Choices/videomode, and the following files in the icewm and jwm packages to support using ~/Choices/windowmanager rather than /etc/windowmanager:
    • pinstall
      /root/.icewm/startup
      /usr/bin/icewm2jwm
      /usr/bin/jwm2icewm
I did not include the modified files for icewm and jwm in the x-stuff.tar.gz package. Pull them out of the ISO if you need them.




Grep and Sed Work

Finally, I did some grep and sed work on a large number of files. The sed command itself was this:

Code: Select all

sed -i 's|/root/|${HOME}/|' <FILENAME>
I don't remember exactly how I came up with the list of files that I used it on, but I believe I first ran a command like this in the packages/ directory of my unleashed tree to locate all packages that had files with '/root/' in them:

Code: Select all

grep -lIR '/root/' * 2>/dev/null | cut -f 1 -d '/' | sort -u > /tmp/list
Then I think I skimmed through the list and culled out packages that I didn't want it to mess with (they seemed like blatenly root-only things, or too nasty to deal with any way but by hand). Then I ran something like this on a couple packages at a time:

Code: Select all

grep --color -IR '/root/' package_1 package_2 package_3
That let me see exactly which parts of which files were involved. If they looked safe to be run through sed I would do something like this:

Code: Select all

find package_1 package_2 package_3 -type f -exec sed -i 's|/root/|${HOME}/|'
The ones that didn't look fine I did by hand.

Since there were so friggin' many, I didn't do a good job of documenting them. Sorry. However, all of the work I've done on this project was done through Git, so I can provide the diff from that commit. That could be perused by and applied by hand, or if you have things laid out the same as my unleashed tree was it could be fed into the patch program. You could probably also feed it through patch without unleashed and just have patch strip off the first three components of the path. I'm not sure how well that would work though because there may be some duplication due to multiple versions of some packages. Anyway, here is the diff file: makestuffuserfriendly.diff




Git (for masochists who want to see exactly what I did)

I used Git when working on Multiuser Puppy. Git isn't for everybody, especially when working on large binary projects such as a Puppy derivatives. Because Git was primarily designed for dealing with source code, not large binary projects, there are a number of pitfalls a person desiring to use it for Puppy development should be aware of. I already wrote a lot of information on the subject when we were considering moving official Puppy development into a Git repository. That information now lives here: (link). You don't need to use Git. But you are free to clone my tree if you want to play around with exactly the build environment I used when creating Multiuser Puppy. My Multiuser Puppy work is under the "multiuser" branch.
git://pizzasgood.no-ip.org/puppy




Conclusion

That sums up what I did to make Multiuser Puppy work. Feel free to ask questions, suggest improvements, and point out gaping security holes I left open. A brief warning: I have no intention to maintain this. My goal was only to forge the path to make a multiuser Puppy possible. I've succeeded in that goal. So I'm moving on to other projects. I will of course still answer any questions and what-not, and maybe address any major problems. But it's up to "you" to reapply this to newer/older versions of Puppy where needed. They shouldn't be different enough to make a huge difference.


Last updated 2009-10-31
Last edited by Pizzasgood on Sun 01 Nov 2009, 01:32, edited 2 times in total.
[size=75]Between depriving a man of one hour from his life and depriving him of his life there exists only a difference of degree. --Muad'Dib[/size]
[img]http://www.browserloadofcoolness.com/sig.png[/img]

User avatar
Nathan F
Posts: 1764
Joined: Wed 08 Jun 2005, 14:45
Location: Wadsworth, OH (occasionally home)
Contact:

#2 Post by Nathan F »

Hi Pizzasgood. I just wanted to offer some of my old code if you're going to continue working in this vein.

Code: Select all

svn checkout http://grafpup-linux.googlecode.com/svn/trunk/ grafpup-linux-read-only
I had a pretty nice user manager gui which put all the basic tasks in one place. Written in gtkdialog, of course. There were also a lot of Puppy programs which I painstakingly went through to make more multi-user friendly. Take whatever looks good to you. I think a lot of it used the same or similar solutions as yours (which from what I've read sounds very elegant) so hopefully it wouldn't be hard to adjust to your scheme.

One suggestion I would make is to add gksu along with the other utilities you've added. If you go for an older version it can be compiled without a lot of gnome libs and makes it so that if a normal user tries to start up a privileged program they can authenticate as root. I had it working pretty well at one time.

If none of it is useful or you just go your own way that's fine, too. Either way good luck with getting this concept accepted hereabouts.

Nathan
Bring on the locusts ...

User avatar
Pizzasgood
Posts: 6183
Joined: Wed 04 May 2005, 20:28
Location: Knoxville, TN, USA

#3 Post by Pizzasgood »

Cool. I'll take a look this weekend or so.
[size=75]Between depriving a man of one hour from his life and depriving him of his life there exists only a difference of degree. --Muad'Dib[/size]
[img]http://www.browserloadofcoolness.com/sig.png[/img]

User avatar
zigbert
Posts: 6621
Joined: Wed 29 Mar 2006, 18:13
Location: Valåmoen, Norway
Contact:

#4 Post by zigbert »

Pizzasgood
You show extreme qualities!

I will deal with the Pwidgets issues for the next Pwidgets release.


Sigmund

User avatar
pri
Posts: 342
Joined: Fri 09 Oct 2009, 18:31
Location: Bandung Indonesia
Contact:

#5 Post by pri »

hey pizzagood

hey there is a single pet to make it mulsti user :D, i want make it for 4.3.1 i am work on it :D
Learning by Doing

User avatar
Pizzasgood
Posts: 6183
Joined: Wed 04 May 2005, 20:28
Location: Knoxville, TN, USA

#6 Post by Pizzasgood »

No, there isn't. Sorry.

Good luck with 4.3.1. That would be pretty cool. :)
[size=75]Between depriving a man of one hour from his life and depriving him of his life there exists only a difference of degree. --Muad'Dib[/size]
[img]http://www.browserloadofcoolness.com/sig.png[/img]

User avatar
pri
Posts: 342
Joined: Fri 09 Oct 2009, 18:31
Location: Bandung Indonesia
Contact:

#7 Post by pri »

its okey :D

but how to make it login automaticaly as user not as root ? if multiuser is actif, it will be ask login and password everytime loged in.
Learning by Doing

User avatar
pri
Posts: 342
Joined: Fri 09 Oct 2009, 18:31
Location: Bandung Indonesia
Contact:

#8 Post by pri »

look like not working for 4.3.1 :( error in useradd command

must find the other way to make it multi user, not willy multi user i think if use puppy, but mybe automatic login as other than root (as user for me) and let it using root directory or whatever, i dont know :D
Learning by Doing

User avatar
Pizzasgood
Posts: 6183
Joined: Wed 04 May 2005, 20:28
Location: Knoxville, TN, USA

#9 Post by Pizzasgood »

Hmmm.... 4.3.x is a bit newer than 4.2, so the binary .pets might now work. If that's the case, you would have to recompile them on 4.3.1. Or it might be that 4.3.1 doesn't have one of their dependencies that 4.2.1 did have.

For automatically logging in, the way Puppy does that for "root" is with the "autologinroot" program, which is run from /etc/inittab.

If that program can log you in as root, then it should definitely be possible to make a program that will log you in as a user.

Doing a quick search, I found the source code from autologinroot:
http://www.murga-linux.com/puppy/viewtopic.php?t=5991

Code: Select all

/*BK auto login */

int main() {
 execlp("login","login","-f","root",0);
}
So it looks like you could maybe change the "root" parameter to whatever user you want. Then you compile it with gcc -o autologinuser autologinroot.c and it will give you a "autologinuser" executable that will log in as whichever user you hardcoded into it. (I would name it "autologin<user>", replacing <user> with the name - so in my case I'd have autologinpizzasgood).

Then you can stick that in /bin/ and edit /etc/inittab to use it instead of autologinroot.

I don't know if that will work, but it might.


Also, instead of hardcoding the user, you could do this:

Code: Select all

#include<unistd.h>
int main(int argc, char *argv[]) {
    if (argc != 2){
        execlp("login","login","-f","root",0);
    } else {
        execlp("login","login","-f",argv[1],0);
    }
}
Then it will login as root by default, but if you run it like "autologinuser bob", it would log in as bob. The only catch is I'm not sure how/if you can add that to inittab to pass the parameter (maybe just put the whole thing in quotes). You might have to play around with it to get that version to work.

But I would start with the hardcoded one, just to make sure that the concept works, and only then try the fancier version.
[size=75]Between depriving a man of one hour from his life and depriving him of his life there exists only a difference of degree. --Muad'Dib[/size]
[img]http://www.browserloadofcoolness.com/sig.png[/img]

User avatar
pri
Posts: 342
Joined: Fri 09 Oct 2009, 18:31
Location: Bandung Indonesia
Contact:

#10 Post by pri »

hello again pizzasgood

now iam was in user mode, but not using user user_utils-0.1.pet but using xonemoreuser-en.tar.gz. like a said before, look like command on user_utils-01.pet not same, i think the command now no longger useradd, but adduser.

xonemoreuser-en.tar.gz. , igot from this : http://www.murga-linux.com/puppy/viewto ... 9&start=60

and i am make a autologinuser and work perfect. every login now iam on user mode. but now i cant go back to root mode to set anything again, when trying logout or exit, there is error said must be suid properly to using logout.

and my question is :
1. how to make i can logout to using root or can command as root to modify user area.
2. i cant using pmount, pmount just work only for sda else /mnt/home. and all sdb and other. (sdc, etc) how to enabke it ?
3. some icon on desktop was missing his icon picture. how it can be happen ?

...................................................

and i was trying to using my idea, login as user but still using /root directory. i think this is the best choise to puppy for me. but i cant using anything to work :D look like puppypc locked /root directory and not permited using it. how to make it enable ? chmod it to some code ? or anything else :D.

to add a user to use /root directory is use command :
adduser -h /root user

.....................................................
Learning by Doing

User avatar
Pizzasgood
Posts: 6183
Joined: Wed 04 May 2005, 20:28
Location: Knoxville, TN, USA

#11 Post by Pizzasgood »

"useradd" only exists if you install the shadow package. Puppy comes with adduser, which is similar, but not as powerful.

To temporarily become root, you can use the su command. It will ask you for the root password, and then you'll have root's permissions in that terminal session until you run "exit" or press CTRL-D, which will return you to your original user permissions.



For logout, it sounds like you might have to run this (as root or via 'su'):

Code: Select all

chmod +s /bin/logout
That is the command to make a program setuid, which means the program will run with the ID of its owner no matter who runs it. In this case, root owns it, so the logout program will run with root privileges.

But you probably have /bin/logout as a symlink to busybox, and it's probably not good to have busybox be setuid.

I don't remember if I tried using logout in Multiuser Puppy 4.2.1. I think I did. But I installed "shadow", which added its own login program. I don't know if that's relevant.



Mounting is something that normally needs to be done as root. I wrote an elaborate daemon/client system that lets you trigger a mount as a user. A simpler way to do it would be with sudo. You could probably install sudo and then give the users who need to be able to mount a rule in sudo that lets them run pmount. (Sudo lets you specify users who can do anything through sudo, but you can also make them more restricted so that they can only run certain commands.) Then they could run "sudo pmount" and use that to mount things. You could probably make a script that adds the sudo for them.



To let a single user (I will name him "bob") live in /root, you could do this:

Code: Select all

chown -R bob /root
But if you want to let multiple users use it, you would have problems. Each user would create files under his own ownership. You could play with the UMASK to maybe help, but it would probably be a losing battle. If you want more than one user you should probably let each user have his own home directory.

Also, even if only a single user is involved, if he logs in as root and does stuff, some of the files in /root might get set to being owned by root again.

Also, it's potentially dangerous to let a user modify things in /root, because then they could add scripts to /root/Startup or /root/.bashrc that would run when root logs in, with root's privileges.



I'm not sure what's wrong with your icons. Maybe something in xonemoreuser is out of date. I've never used that.
[size=75]Between depriving a man of one hour from his life and depriving him of his life there exists only a difference of degree. --Muad'Dib[/size]
[img]http://www.browserloadofcoolness.com/sig.png[/img]

User avatar
pri
Posts: 342
Joined: Fri 09 Oct 2009, 18:31
Location: Bandung Indonesia
Contact:

#12 Post by pri »

i am already using all pet on the fisrt post. but useradd have other problem. this is screnshot.
Attachments
aduser.png
(10.52 KiB) Downloaded 10804 times
Learning by Doing

User avatar
Pizzasgood
Posts: 6183
Joined: Wed 04 May 2005, 20:28
Location: Knoxville, TN, USA

#13 Post by Pizzasgood »

Do you have the appropriate groups? You may need to run these:

Code: Select all

groupadd --system audio
groupadd --system drive
groupadd --system power
groupadd --system wheel
[size=75]Between depriving a man of one hour from his life and depriving him of his life there exists only a difference of degree. --Muad'Dib[/size]
[img]http://www.browserloadofcoolness.com/sig.png[/img]

User avatar
Max Headroom
Posts: 421
Joined: Wed 28 Jun 2006, 07:17
Location: GodZone Kiwi
Contact:

Pizzasgood Could U Please Advise the Relevance of these

#14 Post by Max Headroom »

Pizzasgood Could U Please Advise the Relevance of these instructions w/ Grays NOP 4.3.1 w/ XFCE, I'd Hate 2 Start this then come up 2 a Brick wall that I can't Konquer! :) Thanx :)

User avatar
Pizzasgood
Posts: 6183
Joined: Wed 04 May 2005, 20:28
Location: Knoxville, TN, USA

#15 Post by Pizzasgood »

I'm not as familiar with 4.3.1 as I am with the 4.1.x series since I never used it regularly. Most of the process is probably the same. I think the bootscripts might have changed a little, and some of the package versions are different. Some of the extra scripts I made may or may not work. Most of those are just for simplicity though - e.g. being able to mount/unmount drives and reboot without having to use sudo.

I know nothing at all about what changes gray has made. Maybe there are some hardcoded paths in the XFCE configuration that would need to be adjusted when it is copied into your new home directory (usually config files can't have variable paths and must be hardcoded).

Basically, this can be done on any Puppy, it's just a matter of how much work is involved. The general parts of these directions should apply to just about anything. The more specific stuff - references to individual files, for example - are less broad. You would need to investigate to see if there are any new files that need to be edited that I didn't list. The grep command is great for that kind of thing.
[size=75]Between depriving a man of one hour from his life and depriving him of his life there exists only a difference of degree. --Muad'Dib[/size]
[img]http://www.browserloadofcoolness.com/sig.png[/img]

User avatar
Max Headroom
Posts: 421
Joined: Wed 28 Jun 2006, 07:17
Location: GodZone Kiwi
Contact:

Thanx Pizzasgood 4 Y'r Answer

#16 Post by Max Headroom »

Thanx Pizzasgood 4 Y'r Answer :D

User avatar
ASRI éducation
Posts: 3197
Joined: Sat 09 May 2009, 12:10
Location: France
Contact:

#17 Post by ASRI éducation »

Thank you to Pizzasgood.

I tried to change the 431fr (Toutou), but it's not easy ...

If the multiuser was built in Puppy, life would be simpler.

Barry, if you hear me...

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#18 Post by technosaurus »

This little tool could come in handy as a replacement for sudo, gksu etc.. I added symlinks for gksu, sudo and gksudo, for scripts that may need them.
Attachments
ktsuss-1.4-i486.pet
(9.78 KiB) Downloaded 503 times
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

Post Reply