V22.0480-003 Lab 4: File Server

Due date: Thursday Novermber 8.

Introduction

In this lab you will implement the access control in a simple SFS file server. sfsusrv is an SFS file server implemented in terms of the standard POSIX open/close/read/write calls.
sfsusrv runs as a particular user, and lets that particular user connect to it and access files. However, the semantics of access control are wrong in sfsusrv. For example, if you don't have read permission on a file, you can still open the file (even though a subsequent read will fail). Unix semantics dictate that the open should fail.

Building the sfsusrv software

To get started with the software, you should unpack the existing sfsusrv from ~class/src/sfsusrv.tar.gz. The build process should by now be familiar. This project does not use classfs, so you only need the --with-sfs= argument:
% cd
% tar xzvf ~class/src/sfsusrv.tar.gz
% cd sfsusrv
% sh ./setup
+ aclocal
...
+ set +x
% setenv DEBUG -g
% mkdir /home/c5/yourname
% pushd /home/c5/yourname
/home/c5/yourname ~/sfsusrv
% =1/configure --with-sfs=/usr/local/fs/debug
creating cache ./config.cache
checking for a BSD compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
...
creating Makefile
creating config.h
% gmake
...

Running sfsusrv

Before you run sfsusrv, you need to generate a public/private key pair for use by the server. That way clients can connect securely to your server. Run the following command:
% sfskey gen -P sfs_host_key
 Creating new key for sfs_host_key.
      Key Name: yourname@class5.scs.cs.nyu.edu Press return
You must also create a configuration file for the server, called sfsusrv_config. Pick some directory to export (for example /home/c1/scratch/yourname, and create an sfsusrv_config file with the following contents:
KeyFile sfs_host_key
Export /home/c1/scratch/yourname
Next run sfsusrv. You must supply two arguments: Thus, you might run sfsusrv as follows:
class1% mkdir /home/c1/scratch/export-$USER
class1% echo hello > /home/c1/scratch/export-$USER/test.file
class1% echo export /home/c1/scratch/export-$USER > sfsusrv_config
class1% echo keyfile sfs_host_key >> sfsusrv_config
class1% ./sfsusrv -p 4444 -f sfsusrv_config 
sfsusrv: version 0.0, pid 6273
sfsusrv: No sfssd detected, running in standalone mode.
sfsusrv: Now exporting directory: /var/tmp
sfsusrv: serving /sfs/4444@class1.scs.cs.nyu.edu:zm7g3qj632ymm8pvxsvyzf4a7upvqs7s
The last line that sfsusrv prints is the path name under which your exported directory (/home/c1/scratch/export-$USER) will appear on SFS client machines. Your path will be different from the one printed above. The 4444 is the port number that sfsusrv is listening to. You can log into into a different machine an access the files under /sfs/4444@class1...--pasting in whatever your actual pathname is. Note you cannot access and SFS file server running on the same machine as the client--you will get Resource Deadlock Avoided errors.
class2% sfsagent
Passphrase for /home/c/dm/.sfs/identity: 
class2% cd /sfs/4444@class1.scs.cs.nyu.edu:zm7g3qj632ymm8pvxsvyzf4a7upvqs7s
sfsagent: sfsrwcd_1: class1.scs.cs.nyu.edu:zm7g3qj632ymm8pvxsvyzf4a7upvqs7s (1)
class2% cat test.file
hello
class2% 

Access semantics

Now try the following:
class2% cd /sfs/4444@class1.scs.cs.nyu.edu:zm7g3qj632ymm8pvxsvyzf4a7upvqs7s
class2% chmod 0 test.file
class2% ls -l test.file
----------  1 dm  wheel  0 Nov  3 02:16 test.file
class2% echo < test.file
class2% 
Redirecting standard input to the echo command opens test.file for reading. However, the user does not have read permission to test.file. Thus, the open should fail. Unfortunately, it doesn't. The reason is that sfsusrv does not implement NFSPROC3_ACCESS properly. If you re-run sfsusrv with env ASRV_TRACE=10 ./sfsusrv -p 4444 -f sfsusrv_config (or ``set asrvtrace=10'' inside gdb), you will see something like the following:
sfsusrv: ASRV_TRACE: serve ex_nfs_program_3:ex_NFSPROC3_ACCESS x=3a5 i=1
access3args ARGS = {
  nfs_fh3 object = {
    opaque data%lt;64> = [10] {
      85, d8, 01, 00, 00, 00, 00, 00,
      00, 00
    };
  };
  u_int32_t access = 0x1;
};
sfsusrv: ASRV_TRACE: reply ex_nfs_program_3:ex_NFSPROC3_ACCESS x=3a5
ex_access3res REPLY = {
  nfsstat3 status = NFS3_OK;
  ex_access3resok resok = {
    ex_post_op_attr obj_attributes = {
      bool present = true;
      ex_fattr3 attributes = {
        ftype3 type = NF3REG;
        u_int32_t mode = 0x0;
        u_int32_t nlink = 0x1;
        u_int32_t uid = 0x42b;
        u_int32_t gid = 0x0;
        u_int64_t size = 0x0;
        u_int64_t used = 0x0;
        specdata3 rdev = {
          u_int32_t major = 0x0;
          u_int32_t minor = 0x0;
        };
        u_int64_t fsid = 0x0;
        u_int64_t fileid = 0x1d885;
        nfstime3 atime = {
          u_int32_t seconds = 0x3be399bb;
          u_int32_t nseconds = 0x0;
        };
        nfstime3 mtime = {
          u_int32_t seconds = 0x3be399bb;
          u_int32_t nseconds = 0x0;
        };
        nfstime3 ctime = {
          u_int32_t seconds = 0x3be399c0;
          u_int32_t nseconds = 0x0;
        };
        u_int32_t expire = 0x0;
      };
    };
    u_int32_t access = 0x1;
  };
};
(Recall from the NFSPROC3_ACCESS section of RFC 1813 that 0x1 is ACCESS3_READ.)

The problem here is that the function client::access_check (in cliend.C) has not been implemented yet, and always returns what has been requested. Your task will be to implement this function.

Hints for implementing access

What to hand in

As usual, make a tar.gz file with the command gmake distcheck. Copy sfsusrv-0.0.tar.gz and a typescript file of your testing (on the client side) to ~class/handin/lab4/username.

Useful references