⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nfs.c

📁 LFS.This is a kind of file system.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: nfs.C,v 1.17 2001/10/12 21:27:28 dm Exp $ *//* * * Copyright (C) 2001 David Mazieres (dm@uun.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * */#include "nfs.h"const u_int maxfhiv = 512;AUTH *cryptfs::ao = authopaque_create ();tailq<cryptfs::fhiv, &cryptfs::fhiv::lrulink> cryptfs::ivlruq;u_int cryptfs::fhiv::nfhiv;inline voidxorblock (char *dest, const char *src){  for (u_int i = 0; i < blocksize; i++)    dest[i] ^= src[i];}u_int64_tcryptfs::fhiv::attr2iv (const fattr3exp *f){  /* Note:  We make the iv a deterministic function of the attributes   * in case two clients simultaneously perform UNCHECKED creates of   * the same file.  We could alternatively hash the file handle, but   * in the case of SFS, different clients will have different file   * handles (because sfsrwcd encrypts file handles to make it   * slightly resistant to forged "loopback" traffic). */  u_char buf[sha1::hashsize];  puthyper (buf, f->fileid);  puthyper (buf + 8, f->fsid);  sha1_hash (buf, buf, 16);  return gethyper (buf);}voidcryptfs::fhiv::init (){  cryptfs::ivlruq.insert_tail (this);  cfs->ivtab.insert (this);  nfhiv++;  while (nfhiv > maxfhiv && cfs->ivlruq.first->stable)    delete cfs->ivlruq.first;}voidcryptfs::fhiv::fetchcb (ref<cryptfs> hold, ref<read3res> resp, clnt_stat stat){  if (stat || resp->status || resp->resok->data.size () < blocksize)    err = true;  else {    char *buf = resp->resok->data.base ();    cfs->decrypt (-blocksize, 0, buf, buf);    if (gethyper (buf))      err = true;    else      iv = gethyper (buf + 8);  }  wake ();}voidcryptfs::fhiv::createcb (ref<cryptfs> hold, ref<write3res> resp,			 clnt_stat stat){  if (stat || resp->status)    err = true;  wake ();}voidcryptfs::fhiv::wake (){  stable = valid = true;  touch ();  typedef vec<cbv> ivw_t;  if (ivw_t *p = cfs->ivwait[fh]) {    ivw_t v;    p->swap (v);    cfs->ivwait.remove (fh);    while (!v.empty ())      (*v.pop_front ()) ();  }}cryptfs::fhiv::fhiv (cryptfs *fs, const nfs_fh3 &f, bool isdir)  : cfs (fs), fh (f), iv (0), valid (false), stable (false), err (false){  assert (!isdir);  init ();  read3args arg;  arg.file = fh;  arg.offset = 0;  arg.count = blocksize;  ref<read3res> resp = New refcounted<read3res>;  cfs->call (NFSPROC3_READ, &arg, resp,	     wrap (this, &cryptfs::fhiv::fetchcb, mkref (cfs), resp),	     cfs->ao);}cryptfs::fhiv::fhiv (cryptfs *fs, const nfs_fh3 &f, const fattr3exp *fa)  : cfs (fs), fh (f), iv (attr2iv (fa)),    valid (true), stable (false), err (false){  init ();  write3args arg;  arg.file = fh;  arg.offset = 0;  arg.count = blocksize;  arg.stable = DATA_SYNC;  arg.data.setsize (blocksize);  puthyper (arg.data.base (), 0);  puthyper (arg.data.base () + 8, iv);  cfs->encrypt (-blocksize, 0, arg.data.base (), arg.data.base ());  ref<write3res> resp = New refcounted<write3res>;  cfs->call (NFSPROC3_WRITE, &arg, resp,	     wrap (this, &cryptfs::fhiv::createcb, mkref (cfs), resp),	     cfs->ao);}cryptfs::fhiv::~fhiv (){  cryptfs::ivlruq.remove (this);  cfs->ivtab.remove (this);  nfhiv--;}voidcryptfs::fhiv::touch (){  cryptfs::ivlruq.remove (this);  cryptfs::ivlruq.insert_tail (this);}voidcryptfs::encrypt (u_int64_t offset, u_int64_t iv, char *out, const char *in){  assert (!(offset & 15));  char buf[16];  puthyper (buf, iv);  puthyper (buf + 8, offset);  fskey.encipher_bytes (buf, buf);  xorblock (buf, in);  fskey.encipher_bytes (out, buf);}voidcryptfs::decrypt (u_int64_t offset, u_int64_t iv, char *out, const char *in){  assert (!(offset & 15));  char buf[16];  puthyper (buf, iv);  puthyper (buf + 8, offset);  fskey.encipher_bytes (buf, buf);  fskey.decipher_bytes (out, in);  xorblock (out, buf);}strcryptfs::encodename (u_int64_t diriv, str name){  static str zeros ("\0", 2);  assert (name.len ());  if (name == "." || name == "..")    return name;  name = name << zeros;  mstr b (name.len () + blockmask & ~blockmask);  memcpy (b, name, name.len ());  bzero (b + name.len (), b.len () - name.len ());  fskey.encipher_bytes (b);  for (char *p = b.cstr () + blocksize, *e = b.cstr () + b.len ();       p < e; p += blocksize) {    xorblock (p, p - blocksize);    fskey.encipher_bytes (p);  }  /* Now encrypt backwards in CBC mode, so all output bits depend on   * all input bits. */  for (char *p = b.cstr () + b.len () - 2*blocksize; p >= b; p -= blocksize) {    xorblock (p, p + blocksize);    fskey.encipher_bytes (p);  }  return armor64A (b);}strcryptfs::decodename (u_int64_t diriv, str name){  if (name == "." || name == "..")    return name;  name = dearmor64A (name);  if (name.len () & blockmask)    return NULL;  mstr b (name.len ());  memcpy (b, name, name.len ());  for (char *p = b, *e = b.cstr () + b.len () - blocksize;       p < e; p += blocksize) {    fskey.decipher_bytes (p);    xorblock (p, p + blocksize);  }  for (char *p = b.cstr () + b.len () - blocksize; p > b; p -= blocksize) {    fskey.decipher_bytes (p);    xorblock (p, p - blocksize);  }  fskey.decipher_bytes (b);  *(b.cstr () + b.len ()) = '\0';  u_int blen = strlen (b.cstr ());  if (b.len () - blen < 2)    return NULL;  for (u_int i = blen; i < b.len (); i++)    if (b[i])      return NULL;  b.setlen (blen);  return b;}intcryptfs::getiv (nfs_fh3 &fh, bool stable, const authunix_parms *aup,		cbv::ptr cb, u_int64_t *ivp){  fhiv *fp = ivtab[fh];  if (fp && fp->valid && (fp->stable || !stable)) {    if (ivp)      *ivp = fp->iv;    fp->touch ();    return fp->err ? -1 : 1;  }  if (cb) {    vec<cbv> *p = ivwait[fh];    if (!p) {      ivwait.insert (fh);      p = ivwait[fh];    }    p->push_back (cb);  }    if (!fp) {    authopaque_set (ao, aup);    vNew fhiv (this, fh, false);  }  return 0;}voidcryptfs::fillpoa (nfscall *nc, const nfs_fh3 *fhp,		  post_op_attr *poa, aclnt_cb cb){  ref<getattr3res> ares = New refcounted<getattr3res>;  call (NFSPROC3_GETATTR, fhp, ares,	wrap (mkref (this), &cryptfs::fillpoa_1, nc, poa, ares, cb), ao);}voidcryptfs::fillpoa_1 (nfscall *nc, post_op_attr *poa, ref<getattr3res> ares,		    aclnt_cb cb, clnt_stat stat){  if (stat)    (*cb) (stat);  else if (ares->status)    nc->error (ares->status);  else {    poa->set_present (true);    *poa->attributes = *ares->attributes;    (*cb) (RPC_SUCCESS);  }}voidcryptfs::reply (nfscall *nc, clnt_stat stat){  if (stat) {    warn << "NFS server: " << stat << "\n";    nc->reject (SYSTEM_ERR);    return;  }  else if (nc->proc () == NFSPROC3_NULL) {    nc->reply (NULL);    return;  }  nfs3_exp_enable (nc->proc (), nc->getvoidres ());  xattrvec xv;  nfs3_getxattr (&xv, nc->proc (), nc->getvoidarg (), nc->getvoidres ());  for (xattr *x = xv.base (); x < xv.lim (); x++)    if (x->fattr) {      x->fattr->size = fixsize (x->fattr->type, x->fattr->size);      if (x->wattr)	x->wattr->size = fixsize (x->fattr->type, x->wattr->size);    }    else if (x->wattr)      // without ftype, don't know how to adjust size, so nuke it      x->wdata->before.set_present (false);  nfs3_exp_disable (nc->proc (), nc->getvoidres ());  if (nc->proc () != NFSPROC3_NULL && !*nc->template getres<nfsstat3> ())    switch (nc->proc ()) {    case NFSPROC3_WRITE:      {	write3args *arg = nc->template getarg<write3args> ();	write3res *res = nc->template getres<write3res> ();	res->resok->count -= arg->offset & blockmask;	if (res->resok->count > arg->count)	  res->resok->count = arg->count;	break;      }    case NFSPROC3_READLINK:      {	readlink3res *res = nc->template getres<readlink3res> ();	if (str link = decodename (0, res->resok->data))	  res->resok->data = substr (link, 8);	else	  res->resok->data = "";	break;      }    case NFSPROC3_READDIR:      if (!fixreaddir<NFSPROC3_READDIR> (nc))	return;      break;    case NFSPROC3_READDIRPLUS:      if (!fixreaddir<NFSPROC3_READDIRPLUS> (nc))	return;      break;    case NFSPROC3_ACCESS:      if (aid != sfsaid_nobody && aid != aup2aid (nc->getaup ())	  && (!nc->getaup () || (nc->getaup ()->aup_uid)))	nc->template getres<access3res> ()->resok->access = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -