Kuro http pages for debian

From NAS-Central Buffalo - The Linkstation Wiki
Revision as of 17:49, 19 July 2006 by Dtaylor (Talk)

Jump to: navigation, search

This is an early work in progress ! Still a lot of work to make this complete !

Contents

Introduction

You may know the Kuro-box HTTP interface that allow to manage many things like samba shares and many other things ! As I love these pages, I decided to make them running with Debian !
http5bv.png

Progress

Legend :
(P) = ported thing : It was existing before, but needed some modifications in CGI code or system files
(N) = new feature : It's something new in the interface.
(B) = bug fix : There are some bugs in the administartion pages/scripts, it's better to correct them !

Things done

  • (P) Porting main http structure
  • (P) IP set to 192.168.11.150 if no DHCP server found (and configured to run in DHCP)
  • (P) NTP synchronisation at startup if enabled (needs ntp and ntpdate)
  • (P) NTP cron job at a defined hour if enabled (needs cron)
  • (P) Network link stats in status page (need ethtool)
  • (N) HDD temperature information (need hddtemp)
  • (P) Samba users management (need samba)
  • (B) There is an anoying bug about the workgroup setup not working => Using my scripts, i don't have this bug ...
  • (P) Samba shares handling

Things to do, or not yet finished

  • (P) USB drive handling (need udev & usbmount)
  • (P) AppleTalk management
  • (P) FTP management
  • (P) Automatic backup
  • (P) Kurobox sleep
  • (P) USB printer sharing
  • (N) Add a reboot menu
  • (N) Add some server applications configuration pages (including mt-daapd, amule ...)

Things that people would like to have

Feel free to add anything here (with no garantee it will be added)

Jukebox to play music on your Kuro

Needed packages

For now, these packages are needed :

apt-get install hddtemp ntp ntpdate ethtool cron udev usbmount samba nkf

Needed files

These files are needed for the http pages to work :

/etc/melco/*
/etc/atalk/
/etc/init.d/networking
/etc/init.d/ntpdate
/etc/init.d/mkshinfo
/etc/init.d/chkshare
/etc/cron.d/ntpdate
/etc/timezone
/etc/linkstation_release
/etc/rc2.d/S10ntpdate (ln -s ../init.d/ntpdate S10ntpdate)
/etc/rcS.d/S48mkshinfo (ln -s ../init.d/mkshinfo S48mkshinfo)
/var/www/cgi-bin/*
/var/www/image/*
/var/www/help/*
/var/www/errors/*
/bin/mkcode
/bin/chk_ip
/sbin/mkshinfo
/usr/bin/parse_usbscsi

Scripts to write

There is some applications from melco that are written in C, and we have no access to source ! Some scripts need to be rewritten as they can't work anymore in a 2.6 kernel, or because some applications are not working the same way than before !

mkcode

Known actions

mkcode application is the application that create some configuration files for Samba, Netatalk and xxFTPD

> mkcode
Samba/Netatalk/xxFTPD configuration file generetor: mkcode 1.20/ppc, May 16 2005
for HD-HGLAN(BUFFALO INC.), uses sjis
usage: mkcode options[-s/-a/-f].

It uses the configuration file /etc/melco/shareinfo /etc/melco/shareinfo file looks like that :

share<>all<>all<>Win/Mac<>777<>777<>KURO-BOX Share Folder<>0<>0;
music<>all<>all<>Win/Mac<>777<>777<>KURO-BOX Share Folder<>0<>0;

The template is :

directory name<>users list<>groups list<>OS support<>create mode<>directory mode<>Shared Folder Description<>Folder attribute<>Recycler bin;

with

users list = (empty) : no user can access this share
             all : all users can access this share
             user1 : only user1 can access this share
             user1,user2,... : list of users that can access this share
groups list = (empty) : no groups can access this share
              all : all groups can access this share
              @group1 : all users of group1 can access this share
              @group1,@group2,@... : all users of listed groups can access this share
OS support = Win : Windows Support (aka Samba)
             Mac : MacOS Support (aka Appletalk)
             Win/Mac : Both OS support (Samba & Appletalk)
create mode &
directory mode = 777 : Created files and directories are created with 777 mode (all users can access the files from telnet/ssh)
Folder attributes = 0 : Read/Write
                    1 : Read only
                    2 : Not shared (new feature)
Recycler bin = 0 : disabled
               1 : enabled
Samba configuration file

When calling mkcode -s, mkcode check every entries in /etc/melco/shareinfo and create a /etc/samba/smb.conf file with these sections :

[global]

to be completed

[global]
    client code page = 850
    character set = ISO8859-1
    workgroup = WORKGROUP
    server string = Kuro-Box
    socket options = TCP_NODELAY SO_SNDBUF=12288 SO_RCVBUF=12288
    dns proxy = No
    netbios name = KURO-BOX
    os level = 1
    wins server = 

    security = user
    encrypt passwords = Yes
    obey pam restrictions = Yes
    pam password change = Yes
    passwd program = /usr/bin/passwd %u
    passwd chat = *New*password* %n\n *Retype*new*password* %n\n *passwd:*all*authentication*tokens*updated*successfully*
    unix password sync = yes
    guest account = nobody
    null passwords = yes
    guest only = no
    username level = 12
    password level = 8
    map to guest = Bad User

    browsable = no
    preserve case = yes
    short preserve case = yes
    veto files = /.AppleDesktop/Network Trash Folder/TheVolumeSettingsFolder/.AppleDouble/.AppleDB/
    delete veto files = yes

    invalid users = mail, deamon, adt
    admin users = root
    username map = /etc/samba/smbusers
    
    getwd cache = yes
    printcap name = /etc/printcap
    load printers = yes
    printing = lprng

[lp]

It's the section for printer sharing

[lp]
    comment = Network Printer for Windows
    path = /mnt/spool/samba
    print command = /usr/bin/lpr -Plp -r %s
    printer admin = root
    browsable = yes
    printable = yes
    public = yes
Shared folders sections

Then we have a section per shared folders (list is in /etc/melco/shareinfo) :

[shared_folder]
    comment = comment from /etc/melco/shareinfo
    path = path of the directory (/mnt/shared_folder)
    browsable = yes
    printable = no
    writable = yes (if Folder attributes = 0)/no (if Folder attributes = 1)

if sharing is restricted to some users/groups, then we have that line :

    valid users = user1,user2, @group1,@group2
    force create mode = 777
    force directory mode = 777

if recycler is enabled (Recycler bin = 1), we have these lines :

    vfs object = /usr/lib/samba/recycle.so
    vfs options = /etc/samba/recycle.conf 

Changes because of Samba v3.x.x

HTTP pages were using Samba v2.x.x, but as we're using Samba v3.x.x, we have to update some little things :

The way users are stored

With Samba 2.x.x, we were using smbpasswd to create samba's users, with Samba v3.x.x, we have to use pdbedit

The way the recycler works

Configuration is different, we have to set something like that in the share's section :

vfs object = recycle
        recycle:repository = .trash/
        recycle:keeptree = Yes
        recycle:touch = Yes
        recycle:versions = Yes
        recycle:maxsixe = 0
        recycle:exclude = *.tmp
        recycle:exclude_dir = /tmp
        recycle:noversions = *.doc

Perl script

Warning : it's still a work in progress script even if it allows to generate samba configuration file !

#!/usr/bin/perl
#use strict;

# This script replace original /bin/mkcode application by melco
# History :
# 06/07/19 by sylver : creation

my $fileMELSHARE,$fileMELINFO,$fileMELPRINTER,$fileSMB;
my $localWorkgroup;
my @localTemp;

#input files
$fileMELSHARE="/etc/melco/shareinfo";
$fileMELINFO="/etc/melco/info";
$fileMELPRINTER="/etc/melco/printer";
$fileFTPSTATUS="/etc/melco/ftpstatus";
$fileHOSTS="/etc/hosts";
$fileMTAB="/etc/mtab";

#output files
$fileSMB="/etc/samba/smb.conf";
$fileATALKVOLUMES="/etc/atalk/AppleVolumes.default";
$fileATALKCONFIG="/etc/atalk/config.papd";
$fileFTP="/etc/wu-ftpd/ftpaccess";

print "Samba/Netatalk/xxFTPD configuration file generator: mkcode 0.1 by sylver\n\n";
if ($#ARGV != 0)
  {
  print "usage: mkcode options[-s/-a/-f].";
  exit(0);
  }

#Someone asked to build the samba config file
if ($ARGV[0] eq "-s")
  {
  # building [global] section
  push (@SMB,"[global]\n");
  $localWorkgroup = readpipe("grep \"^wg=\" $fileMELINFO 2> /dev/null");
  chomp $localWorkgroup;
  @localTemp = split /=/, $localWorkgroup;
  push (@SMB,"    workgroup = ".@localTemp[1]."\n");
  push (@SMB,"    server string = %h server (Samba %v)\n"); # TODO : get the correct string
  push (@SMB,"    socket options = TCP_NODELAY SO_SNDBUF=8192 SO_RCVBUF=8192\n"); # TODO : check when to set to TCP_NODELAY SO_SNDBUF=32768 SO_RCVBUF=32768
  push (@SMB,"    dns proxy = No\n");

  $localHostName = readpipe("hostname");
  @localTemp = split /\./, $localHostName;
  $localHostName = $localTemp[0];
  chomp $localHostName;
  push (@SMB,"    netbios name = $localHostName\n");
  push (@SMB,"    os level = 1\n");
  $localWins = readpipe("grep \"^wins=\" $fileMELINFO 2> /dev/null");
  chomp $localWins;
  @localTemp = split /=/, $localWins;
  push (@SMB,"    wins server = ".$localTemp[1]."\n");
  push (@SMB,"\n");
  push (@SMB,"    security = user\n");
  push (@SMB,"    encrypt passwords = true\n");
  push (@SMB,"    passdb backend = tdbsam\n");
  push (@SMB,"    obey pam restrictions = Yes\n");
  push (@SMB,"    pam password change = Yes\n");
  push (@SMB,"    invalid users = root\n");
  push (@SMB,"    passwd program = /usr/bin/passwd %u\n");
  push (@SMB,"    passwd chat = *New*password* %n\\n *Retype*new*password* %n\\n *passwd:*all*authentication*tokens*updated*successfully*\n");
  push (@SMB,"    unix password sync = yes\n");
  push (@SMB,"    guest account = nobody\n");
  push (@SMB,"    null passwords = yes\n");
  push (@SMB,"    guest only = no\n");
  push (@SMB,"    username level = 12\n");
  push (@SMB,"    password level = 8\n");
  push (@SMB,"    map to guest = Bad User\n");
  push (@SMB,"\n");
  push (@SMB,"    browsable = no\n");
  push (@SMB,"    preserve case = yes\n");
  push (@SMB,"    short preserve case = yes\n");
  push (@SMB,"    veto files = /.AppleDesktop/Network Trash Folder/TheVolumeSettingsFolder/.AppleDouble/.AppleDB/\n");
  push (@SMB,"    delete veto files = yes\n");
  push (@SMB,"\n");
  push (@SMB,"    invalid users = mail, deamon, adt\n");
  push (@SMB,"    admin users = root\n");
  push (@SMB,"    username map = /etc/samba/smbusers\n");
  push (@SMB,"    getwd cache = yes\n");
  push (@SMB,"\n");

  #building printer section
  $localPrinter = readpipe("grep \"^printer=\" $fileMELPRINTER 2> /dev/null");
  chomp $localPrinter;
  @localTemp = split /=/, $localPrinter;
  if($localTemp[1] eq "on")
    {
    push (@SMB,"    printcap name = /etc/printcap\n");
    push (@SMB,"    load printers = yes\n");
    push (@SMB,"    printing = lprng\n");
    push (@SMB,"\n");
    }
  push (@SMB,"    include = /etc/samba/smb.conf.kuro\n");

  # Building shares sections
  # Template of MELSHARE file :
  # directory name<>users list<>groups list<>OS support<>create mode<>directory mode<>Shared Folder Description<>Folder attribute<>Recycler bin;
  #       0              1            2           3           4               5                   6                      7               8
  open (FILE, "$fileMELSHARE" );
  foreach $LINE (<FILE>)
      {
      chomp $LINE;
      @localTemp = split /<>/, $LINE;
      # If folder attribute = 2, then don't share the folder !
      if ($localTemp[7] != 2)
        {
        push (@SMB,"[".$localTemp[0]."]\n");
        push (@SMB,"    comment = ".$localTemp[6]."\n");
        push (@SMB,"    path = /mnt/".$localTemp[0]."\n");
        push (@SMB,"    browsable = yes\n");
        push (@SMB,"    printable = no\n");
        push (@SMB,"    writable = ");
        if ($localTemp[7] == 0)
          {
          push (@SMB,"yes\n");
          }
        else
          {
          push (@SMB,"no\n");
          }

        if (($localTemp[1] eq "all") || ($localTemp[2] eq "all"))
          {
          push (@SMB,"    guest ok = yes\n");
          }
        else
          {
          push (@SMB,"    valid users = ".$localTemp[1].",".$localTemp[2]."\n");
          }
        push (@SMB,"    force create mode = ".$localTemp[4]."\n");
        push (@SMB,"    force directory mode = ".$localTemp[5]."\n");
        if ($localTemp[8] == 1)
          {
          push (@SMB,"    vfs object = recycle\n");
          push (@SMB,"            recycle:repository = .trash/\n");
          push (@SMB,"            recycle:keeptree = Yes\n");
          push (@SMB,"            recycle:touch = Yes\n");
          push (@SMB,"            recycle:versions = Yes\n");
          push (@SMB,"            recycle:maxsixe = 0\n");
          push (@SMB,"            recycle:exclude = *.tmp\n");
          push (@SMB,"            recycle:exclude_dir = /tmp\n");
          push (@SMB,"            recycle:noversions = *.doc\n");
          }
        push (@SMB,"###".$localTemp[0]."###\n");
        }
      }

  close(FILE);

  #
  # USB and CD/DVD drives sharing
  #

  $localUSBSHARE = readpipe("grep \"^usbdisk=\" $fileMELINFO 2> /dev/null");
  chomp $localUSBSHARE;
  @localTemp = split /=/, $localUSBSHARE;
  if($localTemp[1] eq "on")
    {
    $cpt_usb=1;
    $cpt_cd=1;
    open (FILE, $fileMTAB );
    foreach $LINE (<FILE>)
      {
      $localUSB = readpipe("echo \"$LINE\" | grep \"\/mnt2\/\" 2> /dev/null");
      if ($localUSB)
        {
        chomp $localUSB;
        @localUSB = split / /, $localUSB;
        @localTemp = split /\//, $localUSB[1];
        push (@SMB,"[".$localTemp[2]."]\n");
        if ($localTemp[2] eq "cdrom")
          {
          push (@SMB,"    comment = CD-ROM ".$cpt_cd."\n");
          $cpt_cd++;
          }
        else
          {
          push (@SMB,"    comment = USB HDD ".$cpt_usb."\n");
          $cpt_usb++;
          }
        push (@SMB,"    path = ".$localUSB[1]."\n");
        push (@SMB,"    browsable = yes\n");
        push (@SMB,"    writable = yes\n");
        push (@SMB,"    printable = no\n");
        push (@SMB,"    guest ok = yes\n");
        push (@SMB,"    force create mode = 777\n");
        push (@SMB,"    force directory mode = 777\n");
        push (@SMB,"###".$localTemp[2]."###\n");
        }
      }
    close(FILE);
    }

  push (@SMB,"#####END#####\n");

  open (FILE,">$fileSMB");
  print FILE @SMB ;
  close(FILE);
  print "done.\n";
  }

#Someone asked to build the AppleTalk config file
if ($ARGV[0] eq "-a")
  {
  print "Appletalk configuration not yet implemented"
#  print "done.";
  }

#Someone asked to build the FTP config file
if ($ARGV[0] eq "-f")
  {
  print "FTP configuration not yet implemented"
#  print "done.";
  }

Things to improve

Done :

  • You can now tell that you don't want to share a folder in /mnt !

mkshinfo

Known actions

Check folders in /mnt and add unconfigured folders in /etc/melco/shareinfo. Check /etc/melco/shareinfo and creates unexisting shares in /mnt. The original application was sharing folders that where not already in the shareinfo file, but now that we can tell not to share a folder, if the folder have been created by hand, we can consider that we don't want to share it !

Perl script

#!/usr/bin/perl
#use strict;

# This script replace original /sbin/mkshinfo application by melco
# History :
# 06/07/19 by sylver : creation

# First step is to parse the shareinfo file to check if every directory exists. If it doesn't exist, then create it in /mnt
# Second step is to parse the /mnt and to add a default configuration in shareinfo file for directories that are not already in it 

#input files
$fileMELSHARE="/etc/melco/shareinfo";

# Template of MELSHARE file :
# directory name<>users list<>groups list<>OS support<>create mode<>directory mode<>Shared Folder Description<>Folder attribute<>Recycler bin;
#       0              1            2           3           4               5                   6                      7               8

#
# Check for some missing /mnt directories
#
open (FILE, "$fileMELSHARE" );
foreach $LINE (<FILE>)
    {
    chomp $LINE;
    @localTemp = split /<>/, $LINE;
    # if the directory is different from "none" and doesn't exist, then create it
    if (($localTemp[0] ne "none")&&(! -d "/mnt/$localTemp[0]"))
      {
      system ("mkdir -p /mnt/$localTemp[0] > /dev/null 2>&1");
      chmod 0777 ,"/mnt/$localTemp[0]";
      }
    }
close(FILE);

#
# Check for some missing configuration in shareinfo file
#

# Mark the shareinfo file as not beeing blank
$shareBlank = 0;

@files_found = </mnt/*>;
for($file=0;$file<@files_found;$file++)
  {
  if ( -d $files_found[$file])
    {
    # Extract the directory name
    @shareName = split /\//, $files_found[$file];

    #
    # Parse shareinfo to find if it's already configured
    #
    # Template of MELSHARE file :
    # directory name<>users list<>groups list<>OS support<>create mode<>directory mode<>Shared Folder Description<>Folder attribute<>Recycler bin;
    #       0              1            2           3           4               5                   6                      7               8
    $shareFound = 0;
    open (FILE, "$fileMELSHARE" );
    foreach $LINE (<FILE>)
      {
      chomp $LINE;
      @localTemp = split /<>/, $LINE;
      if ($localTemp[0] eq "none")
        {
        # the file is blank, remember that to rewrite it instead of append !
        $shareBlank = 1;
        }
      if ( $localTemp[0] eq $shareName[2])
        {
        $shareFound = 1;
        }
      }
    close (FILE);
    if ($shareFound == 0)
      {
      chmod 0777 ,"/mnt/$shareName[2]";
      push (@SHAREINFO,"$shareName[2]<>all<>all<>Win/Mac<>777<>777<>KURO-BOX Share Folder<>2<>0;\n");
      }
    }
  }

#
# If there are some new folders, add them in shareinfo file
#
if (@SHAREINFO)
  {
  if ($shareBlank == 1)
    {
    # Open to write
    open (FILE, ">$fileMELSHARE");
    }
  else
    {
    # Open to append
    open (FILE, ">>$fileMELSHARE");
    }
  print FILE @SHAREINFO;
  close (FILE);
  }

chk_ip

Known actions

It checks that the given IP address and subnet address are correct (it's called when you want to fix kurobox's IP) :

> chk_ip ip_address subnet_address

Forbidden IP address :

  • 0.0.0.0 (network address)
IP address is network address!
  • 127.0.0.1 (loopback)
IP address is reserved!
  • 255.255.255.255 (broadcast)
IP address is broadcast address!
  • class D addresses : 224.0.0.0 to 239.255.255.255
IP address is Class D
  • class E addresses : 240.0.0.0 to 255.255.255.254
IP address is Class E
  • If submask address is 255.255.255.255
IP address is broadcast address!
  • If address and submask are ok :
IP address and sub netmask is correct

Perl script

#!/usr/bin/perl
#use strict;

# This script replace original /bin/chk_ip application by melco
# History :
# 06/07/19 by sylver : creation

if ($#ARGV != 1)
  {
  print "usage: chk_ip xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx\n";
  exit(1);
  }

if ($ARGV[0] eq "0.0.0.0")
  {
  print "IP address is network address!\n";
  exit(1);
  }

if ($ARGV[0] eq "127.0.0.1")
  {
  print "IP address is reserved!\n";
  exit(1);
  }

if (($ARGV[0] eq "255.255.255.255")||($ARGV[1] eq "255.255.255.255"))
  {
  print "IP address is broadcast address!\n";
  exit(1);
  }

# Get first IP value to check address class
@localTemp = split /\./, $ARGV[0];
if (($localTemp[0] >= 224) && ($localTemp[0] < 240))
  {
  print "IP address is Class D\n";
  exit(1);
  } 

if ($localTemp[0] >= 240)
  {
  print "IP address is Class E\n";
  exit(1);
  }

print "IP address and sub netmask are correct\n";
exit(0);

parse_usbscsi

Known actions

It's parsing /proc/scsi/usb-storage-*/* to find supported devices and fills to files with some information :

  • /mnt2/usbinfo/list that contains a list of /dev/sd? devices plugged. For example :
> cat /mnt2/usbinfo/list
/dev/sda
/dev/sdc
  • /mnt2/usbinfo/exist that contains several informations separated by ',' :
> cat /mnt2/usbinfo/exist
/dev/sda,00JB-55GVA0     ,HDD 
/dev/sdc,HA250JC         ,HDD

Original parse_usbscsi only supports devices tagged in /proc/scsi/scsi as "Type:" equal to

  • Direct-Access
  • Optical Device
  • Optical-Device
  • HardDisk
  • Hard Disk

There are 2 problems :

  • In 2.6 kernel, USB devices are stored in /proc/scsi/usb-storage/* (0,1,2 ...)
  • Limiting support for listed types will prevent most of the USB thumbdrives to work

We will correct these 2 problems with our script ;)

Perl script

This script is working, but it's not written in the best way (it's calling 'awk' command but this part should be rewritten in PERL by someone who knows PERL better than me). For now the /mnt2/usbinfo/exist output is wrong but it seems to work that way. I'll correct that later.

#!/usr/bin/perl
#use strict;

# This script replace original /usr/bin/parse_usbscsi application by melco
# History :
# 06/07/19 by sylver : creation

# if running a 2.4.x kernel
# use /proc/scsi/usb-storage-*/*
# else (2.6.x kernel)
# use /proc/scsi/usb-storage/*

$localKernel24 = readpipe("uname -r | grep \"2.4.\" 2> /dev/null");
if ($localKernel24)
  {
  $localSCSIFiles = "/proc/scsi/usb-storage-*/*";
  }
else
  {
  $localSCSIFiles = "/proc/scsi/usb-storage/*";
  }

# fill /mnt2/usbinfo/exist :
# run awk '$1 ~ /Host/ && $3 ~ /usb-storage/ {printf "/dev/sd%c,", substr($2, 5, length($2) - 5) + 97}' $localSCSIFiles >/mnt2/usbinfo/exist
# This command is based on "nix" work (from linkstationwiki). It should be converted to perl.
system("awk '\$1 ~ /Host/ && \$3 ~ /usb-storage/ {printf \"/dev/sd%c,\", substr(\$2, 5, length(\$2) - 5) + 97}' $localSCSIFiles >/mnt2/usbinfo/exist");

# fill /mnt2/usbinfo/list :
# run awk '$1 ~ /Host/ && $3 ~ /usb-storage/ {printf "/dev/sd%c\n", substr($2, 5, length($2) - 5) + 97}' $localSCSIFiles >/mnt2/usbinfo/list
# This command is based on "nix" work (from linkstationwiki). It should be converted to perl.
system("awk '\$1 ~ /Host/ && \$3 ~ /usb-storage/ {printf \"/dev/sd%c\\n\", substr(\$2, 5, length(\$2) - 5) + 97}' $localSCSIFiles >/mnt2/usbinfo/list");

exit (0);

Links

There are some usefull things to read there :