📄 nfs.c
字号:
break; } nc->reply (nc->getvoidres ());}voidcryptfs::reply_create (nfscall *nc, ptr<lookup3res> lres, ptr<getattr3res> ares, clnt_stat stat){ if (stat) { reply (nc, stat); return; } create3args *argp = nc->template getarg<create3args> (); diropres3 *resp = nc->template getres<diropres3> (); authopaque_set (ao, nc->getaup ()); if (!resp->resok->obj.present) { if (!lres) { lres = New refcounted<lookup3res>; call (NFSPROC3_LOOKUP, &argp->where, lres, wrap (mkref (this), &cryptfs::reply_create, nc, lres, ares), ao); return; } else if (lres->status) { nc->error (lres->status); return; } resp->resok->obj.set_present (true); *resp->resok->obj.handle = lres->resok->object; } if (!resp->resok->obj_attributes.present) { if (lres && lres->resok->obj_attributes.present) resp->resok->obj_attributes = lres->resok->obj_attributes; else if (!ares) { ares = New refcounted<getattr3res>; call (NFSPROC3_GETATTR, &*resp->resok->obj.handle, ares, wrap (mkref (this), &cryptfs::reply_create, nc, lres, ares), ao); return; } else if (ares->status) { nc->error (ares->status); return; } else { resp->resok->obj_attributes.set_present (true); *resp->resok->obj_attributes.attributes = *ares->attributes; } } if (!resp->resok->obj_attributes.attributes->size) vNew fhiv (this, *resp->resok->obj.handle, &*resp->resok->obj_attributes.attributes); else resp->resok->obj_attributes.attributes->size = fixsize (resp->resok->obj_attributes.attributes->type, resp->resok->obj_attributes.attributes->size); nc->reply (nc->getvoidres ());}voidcryptfs::reply_read (nfscall *nc, clnt_stat stat){ if (stat) { reply (nc, stat); return; } read3res *res = nc->template getres<read3res> (); if (res->status || !res->resok->data.size ()) { reply (nc, stat); return; } read3args *arg = nc->template getarg<read3args> (); u_int64_t iv; switch (getiv (arg->file, false, nc->getaup (), wrap (mkref (this), &cryptfs::reply_read, nc, stat), &iv)) { case 0: return; case -1: nc->error (NFS3ERR_IO); return; } rpc_bytes<RPC_INFINITY> data; swap (res->resok->data, data); char *p = data.base (), *e = p + (data.size () & ~blockmask); u_int64_t pos = arg->offset & ~blockmask; for (; p < e; p += blocksize, pos += blocksize) decrypt (pos, iv, p, p); u_int skip = arg->offset & blockmask; u_int count = data.size (); if (res->resok->eof && (count & blockmask)) count -= blocksize; count -= skip; if (count > arg->count) count = arg->count; res->resok->data.set (data.base () + skip, count); res->resok->count = count; reply (nc, stat);}voidcryptfs::reply_write (nfscall *nc, u_int64_t end, clnt_stat stat){#ifdef CFSASYNC if (!stat && !*nc->template getres<nfsstat3> () && nc->proc () == NFSPROC3_WRITE) verf = nc->template getres<write3res> ()->resok->verf;#endif /* CFSASYNC */ if (!stat && !*nc->template getres<nfsstat3> () && ((nc->proc () == NFSPROC3_WRITE && nc->template getarg<write3args> ()->stable != UNSTABLE) || nc->proc () == NFSPROC3_COMMIT)) switch (getiv (*nc->getfh3arg (), true, nc->getaup (), wrap (mkref (this), &cryptfs::reply, nc, stat))) { case -1: nc->error (NFS3ERR_IO); return; case 0: return; } /* Plaintext files that are not a multiple of 16 bytes in length * have 16 bytes added to ciphertext files. Thus, while a 16 byte * file is only 16 bytes, a 15 byte file is actually 31 bytes. * * This causes a problem when, for instance, appending one byte to a * 15 byte file--the resulting ciphertext file will still be 31 * bytes, so the plaintext file will still appear to be 15 bytes. * * We must correct the problem by truncating files in this situation. */ if (nc->proc () == NFSPROC3_WRITE && !(end & blockmask)) { post_op_attr *poa = &nc->template getres<write3res> ()->resok->file_wcc.after; if (!poa->present) fillpoa (nc, nc->getfh3arg (), poa, wrap (this, &cryptfs::reply_write, nc, end)); else if (poa->attributes->size < end + blocksize && poa->attributes->size > end) { setattr3args arg; arg.object = *nc->getfh3arg (); arg.new_attributes.size.set_set (true); *arg.new_attributes.size.val = end; arg.guard.set_check (true); *arg.guard.ctime = poa->attributes->ctime; static wccstat3 garbage; call (NFSPROC3_SETATTR, &arg, &garbage, wrap (mkref (this), &cryptfs::reply, nc), ao); return; } } reply (nc, stat);}voidcryptfs::reply_write_read (nfscall *nc, ptr<read3res> rres, clnt_stat stat){ if (stat) { reply (nc, stat); return; } if (rres && rres->status) { nc->template getres<write3res> ()->set_status (rres->status); reply (nc, stat); return; } write3args *argp = nc->template getarg<write3args> (); u_int64_t iv; switch (getiv (argp->file, false, nc->getaup (), wrap (mkref (this), &cryptfs::reply_write_read, nc, rres, stat), &iv)) { case 0: return; case -1: nc->error (NFS3ERR_IO); return; } rpc_bytes<RPC_INFINITY> data; write3args arg = *argp; u_int64_t offset = arg.offset & ~blockmask; u_int32_t count = arg.count + (arg.offset & blockmask); if (count & blockmask) { if (rres->resok->eof) count += blocksize; else count = count + blockmask & ~blockmask; } if (rres) { data.setsize (count); bzero (data.base () + data.size () - blocksize, blocksize); if (rres->resok->data.size () >= blocksize) { decrypt (offset, iv, data.base (), rres->resok->data.base ()); u_int32_t lastblk = (count & ~blockmask) - blocksize; if (lastblk + blocksize <= rres->resok->data.size ()) decrypt (offset + lastblk, iv, data.base () + lastblk, rres->resok->data.base () + lastblk); } memcpy (data.base () + (arg.offset - offset), arg.data.base (), arg.data.size ()); swap (data, arg.data); arg.offset = offset; arg.count = count; } assert (arg.offset == offset && arg.count == count); for (char *p = arg.data.base (), *e = p + (arg.data.size () & ~blockmask); p < e; p += blocksize, offset += blocksize) encrypt (offset, iv, p, p); authopaque_set (ao, nc->getaup ()); call (nc->proc (), &arg, nc->getvoidres (), wrap (mkref (this), &cryptfs::reply_write, nc, argp->offset + argp->count), ao);}voidcryptfs::nfsdispatch (nfscall *nc){ authopaque_set (ao, nc->getaup ()); switch (nc->proc ()) { case NFSPROC3_LINK: fixdirop (&nc->template getarg<link3args> ()->link); break; case NFSPROC3_RENAME: fixdirop (&nc->template getarg<rename3args> ()->from); fixdirop (&nc->template getarg<rename3args> ()->to); break; case NFSPROC3_SYMLINK: { symlink3args *arg = nc->template getarg<symlink3args> (); fixdirop (&arg->where); u_int64_t h; rnd.getbytes (&h, sizeof (h)); arg->symlink.symlink_data = encodename (0, armor64A (&h, 6) << arg->symlink.symlink_data); break; } case NFSPROC3_LOOKUP: case NFSPROC3_MKDIR: case NFSPROC3_MKNOD: case NFSPROC3_REMOVE: case NFSPROC3_RMDIR: fixdirop (static_cast<diropargs3 *> (nc->getvoidarg ())); break; case NFSPROC3_SETATTR: { setattr3args *arg = nc->template getarg<setattr3args> (); if (arg->new_attributes.size.set) { *arg->new_attributes.size.val += datashift; if (*arg->new_attributes.size.val & blockmask) *arg->new_attributes.size.val += blocksize; } // XXX - need to zero out the file if growing it break; } case NFSPROC3_CREATE: fixdirop (static_cast<diropargs3 *> (nc->getvoidarg ())); call (nc->proc (), nc->getvoidarg (), nc->getvoidres (), wrap (mkref (this), &cryptfs::reply_create, nc, ptr<lookup3res> (NULL), ptr<getattr3res> (NULL)), ao); return; case NFSPROC3_READ: { nc->template getarg<read3args> ()->offset += datashift; read3args arg = *nc->template getarg<read3args> (); getiv (arg.file, false, nc->getaup ()); arg.count += arg.offset & blockmask; if (arg.count & blockmask) arg.count += blocksize; // More than needed to decrypt, to get eof flag arg.offset &= ~blockmask; call (nc->proc (), &arg, nc->getvoidres (), wrap (mkref (this), &cryptfs::reply_read, nc), ao); return; } case NFSPROC3_WRITE: { // XXX - need to zero out the file if writing beyond end write3args *arg = nc->template getarg<write3args> ();#ifdef CFSASYNC arg->stable = UNSTABLE;#endif /* CFSASYNC */ getiv (arg->file, false, nc->getaup ()); arg->offset += datashift; if (arg->offset & blockmask || arg->count & blockmask) { read3args rarg; rarg.file = arg->file; rarg.offset = arg->offset & ~blockmask; rarg.count = arg->count + (arg->offset & blockmask); if (rarg.count & blockmask) rarg.count += blocksize; // To get eof flag in read ref<read3res> rres = New refcounted<read3res>; call (NFSPROC3_READ, &rarg, rres, wrap (mkref (this), &cryptfs::reply_write_read, nc, rres), ao); } else reply_write_read (nc, NULL, RPC_SUCCESS); return; } case NFSPROC3_COMMIT: {#ifdef CFSASYNC commit3res res (NFS3_OK); res.resok->verf = verf; nc->reply (&res); return;#endif /* CFSASYNC */ commit3args *arg = nc->template getarg<commit3args> (); arg->offset += datashift; arg->count += arg->offset & blockmask; arg->count = arg->count + blockmask & blockmask; call (nc->proc (), nc->getvoidarg (), nc->getvoidres (), wrap (mkref (this), &cryptfs::reply_write, nc, arg->offset + arg->count), ao); return; } } call (nc->proc (), nc->getvoidarg (), nc->getvoidres (), wrap (mkref (this), &cryptfs::reply, nc), ao);}cryptfs::cryptfs (sfs_aid a, ref<nfsserv> s, clnt_t c, str pwd, int fd) : nfsc (c), nfss (s), fsfd (fd), aid (a){ char key[sha1::hashsize]; sha1_hash (key, pwd, pwd.len ()); fskey.setkey (key, 16); bzero (key, sizeof (*key)); nfss->setcb (wrap (this, &cryptfs::nfsdispatch));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -