/* * SGCOPY.C V1.1 * * DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved. * * GET-COPY SERVER (NEW COPY SERVER) * * The current version only accepts one connection at a time. This server * will send requested files to the remote machine. * * length in 68000 longword format. * * ACCESS RESTRICTIONS: * * Remote access restrictions are according to DNET_GROUP or DNET_READ * * DNET_READ >= 9 Full Access * DNET_READ < 9 According to comment field (AC=n) or group acc. * (GR=n) matches DNET_GROUP) * * When searching for access rights, the comment field of the file/dir * requested is checked first. If empty, the parent dir is checked. * This continues (parent diring) until root is found or a comment * field with access info in it. */ #include "defs.h" typedef struct { char Cmd; char Str[64]; long Val; } HDR; extern int Enable_Abort; char Buf[8192]; void *Chan; void SGCopy ARGS((void)); int PutObject ARGS((char *)); int PutDir ARGS((char *, int)); int PutFile ARGS((char *, int)); int WriteHeader ARGS((char, char *, long)); int ReadHeader ARGS((HDR *)); int brk() { return(0); } void #ifdef LATTICE _main(str) #else _main(len,str) #endif char *str; { struct MsgPort *port; PROC *myproc = (PROC *)FindTask(NULL); long savedir; long mask, rmask; onbreak(brk); if (strncmp(str, "__dnet", 6) != 0) { Version("SGCopy", VERSION, SGCOPY_VERSION); _exit(0); } port = DListen(PORT_GFILECOPY); WaitPort(&myproc->pr_MsgPort); ReplyMsg(GetMsg(&myproc->pr_MsgPort)); savedir = Lock("", SHARED_LOCK); /* duplicate current dir */ if (!savedir) { DUnListen(port); _exit(1); } savedir = CurrentDir(savedir); /* CD dup, returns original */ mask = SIGBREAKF_CTRL_C|(1 << port->mp_SigBit); for (;;) { long dupdir = DupLock(myproc->pr_CurrentDir); rmask = Wait(mask); if (rmask & SIGBREAKF_CTRL_C) { UnLock(CurrentDir(dupdir)); break; } while (Chan = DAccept(port)) { SGCopy(); DClose(Chan); } UnLock(CurrentDir(dupdir)); } UnLock(CurrentDir(savedir)); /* restore original */ DUnListen(port); } void SGCopy() { short error; static HDR Hdr; error = WriteHeader('H', "Hello, GCopy server V1.30", 0); if (error) return; switch(ReadHeader(&Hdr)) { case -1: return; case 'H': break; } while (!error) { switch(ReadHeader(&Hdr)) { case 'G': error = PutObject(Hdr.Str); break; case 'E': goto done; case 'P': /* put-files, not implemented */ default: error = 1; break; } } done: ; } int PutObject(str) char *str; { long lock; FIB *fib = malloc(sizeof(FIB)); short error = 0; short access = GetEnvVal(DNET_READ); short group = GetEnvVal(DNET_GROUP); mountrequest(0); lock = Lock(str, SHARED_LOCK); mountrequest(1); if (lock == NULL || !Examine(lock, fib)) { /* unable to find it! */ error = WriteHeader('N', "Unable to find object", 0); goto done; } /* * Determine Access rights * * If the file/dir or any parent dir has AC > your_ac, access is * denied. If the file/dir and all parent dirs have neither an ACcess * or GRoup entry, access is denied. If a group entry is found that * matches your group, access is allowed (unless an AC is found > your_ac) * * If your_ac is >= 9, no access checking of parent directories is * done at all. However, access checking of downloaded files will * be done, and any AC values > your_ac will be disalloweds. */ if (access < 9) { /* must check comment/access */ short ok = 0; long lock2 = DupLock(lock); long tmp; for (;;) { short ac = 0; while (ac >= 0) { /* check groups */ short idx = 0; ac = ExtractFieldVal(fib->fib_Comment, FS_GROUP, &idx); if (ac >= 0 && ac == group) { ok = 1; break; } } ac = ExtractFieldVal(fib->fib_Comment, FS_ACCESS, NULL); if (ac >= 0) { /* valid access field */ if (ac <= access) { /* access ok */ ok = 1; } else { /* access not ok */ ok = 0; break; } } if (tmp = ParentDir(lock2)) { /* check the par.dir */ UnLock(lock2); lock2 = tmp; fib->fib_Comment[0] = 0; Examine(lock2, fib); continue; } break; } UnLock(lock2); if (!ok) { error = WriteHeader('N', "Access Violation", 0); goto done; } } Examine(lock, fib); UnLock(lock); lock = NULL; if (fib->fib_DirEntryType > 0) { error = PutDir(str, access); } else { error = PutFile(str, access); } done: if (lock) UnLock(lock); free(fib); return((int)error); } int PutDir(name, access) char *name; int access; { long lock = Lock(name, SHARED_LOCK); FIB *fib = malloc(sizeof(FIB)); static HDR Hdr; short error = 0; short ac; if (!lock || !Examine(lock, fib)) { WriteHeader('N', "Possible Disk Error", 0); error = 1; goto done; } ac = ExtractFieldVal(fib->fib_Comment, FS_ACCESS, NULL); if (ac >= 0 && ac > access) { error = WriteHeader('S', fib->fib_FileName, 0); goto done; } if (error = WriteHeader('D', fib->fib_FileName, 0)) goto done; switch(ReadHeader(&Hdr)) { case 'Y': break; case 'S': goto done; case 'N': error = 1; break; default: error = 1; break; } if (error) goto done; while (ExNext(lock, fib)) { /* try to give him the files */ if (fib->fib_DirEntryType > 0) { long oldlock = CurrentDir(lock); error = PutDir(fib->fib_FileName, access); CurrentDir(oldlock); if (error) break; } else { long oldlock = CurrentDir(lock); error = PutFile(fib->fib_FileName, access); CurrentDir(oldlock); if (error) break; } } if (!error) WriteHeader('E', "Possible Disk Error", 0); done: free(fib); if (lock) UnLock(lock); return((int)error); } int PutFile(name, access) char *name; int access; { long lock = Lock(name, SHARED_LOCK); long fh = NULL; FIB *fib = malloc(sizeof(FIB)); static HDR Hdr; long len; short error = 0; short ac; if (!lock || !Examine(lock, fib)) { WriteHeader('N', "Possible Disk Error", 0); error = 1; goto done; } ac = ExtractFieldVal(fib->fib_Comment, FS_ACCESS, NULL); if (ac >= 0 && ac > access) { error = WriteHeader('S', fib->fib_FileName, 0); goto done; } fh = Open(name, 1005); if (fh == NULL) /* don't do anything if unable to open it */ goto done; Seek(fh, 0L, 1); len = Seek(fh, 0L, 0); if (error = WriteHeader('F', fib->fib_FileName, len)) goto done; switch(ReadHeader(&Hdr)) { case 'Y': Seek(fh, Hdr.Val, -1); /* start pos. */ len -= Hdr.Val; if (len < 0) len = 0; break; case 'S': goto done; case 'N': error = 1; break; default: error = 1; break; } if (error) goto done; while (len) { long n = (len > sizeof(Buf)) ? sizeof(Buf) : len; if (Read(fh, Buf, n) != n) { /* read failed! */ error = 10; goto done; } if (DWrite(Chan, Buf, n) != n) { error = 10; goto done; } len -= n; } done: free(fib); if (fh) Close(fh); if (lock) UnLock(lock); return((int)error); } int WriteHeader(c, str, len) char c; char *str; long len; { ubyte sl; if (str == NULL) str = ""; sl = strlen(str); if (DWrite(Chan, &c, 1) < 0) return(1); if (DWrite(Chan, &sl,1) < 0) return(1); if (DWrite(Chan, str, sl) != sl) return(1); if (DWrite(Chan, &len, 4) != 4) return(1); return(0); } int ReadHeader(hdr) HDR *hdr; { ubyte sl; ubyte cmd; hdr->Cmd = -1; if (DRead(Chan, &cmd, 1) != 1) return(-1); if (DRead(Chan, &sl, 1) != 1) return(-1); if (sl >= sizeof(hdr->Str)) { return(-1); } if (DRead(Chan, hdr->Str, sl) != sl) return(-1); hdr->Str[sl] = 0; if (DRead(Chan, &hdr->Val, 4) != 4) return(-1); hdr->Cmd = cmd; return((int)hdr->Cmd); }