func rm(uuid uint64, conn net.Conn, r *bufio.Reader, w *bufio.Writer, md *MDService) (err error) { // get currentDir currentDir, _ := r.ReadString('\n') currentDir = strings.TrimSpace(currentDir) // get len args for rmdir lenArgs, _ := r.ReadByte() // only does something if more than "rmdir" is called, as above for i := 1; i < int(lenArgs); i++ { targetPath, _ := r.ReadString('\n') targetPath = strings.TrimSpace(targetPath) if !path.IsAbs(targetPath) { targetPath = path.Join(currentDir, targetPath) } fmt.Printf("\tUser %d called rm on: \"%s\"\n", uuid, targetPath) src, err := os.Stat(md.getPath() + "files" + targetPath) hidden := utils.IsHidden(targetPath) if hidden { fmt.Printf("\tCall to hidden filepath \"%s\" is not permitted\n", targetPath) } if !hidden && err == nil && !src.IsDir() && checkBase(uuid, targetPath, "w", md) { os.Remove(md.getPath() + "files" + targetPath) } } return nil }
func rmdir(uuid uint64, conn net.Conn, r *bufio.Reader, w *bufio.Writer, md *MDService) (err error) { // get currentDir currentDir, _ := r.ReadString('\n') currentDir = strings.TrimSpace(currentDir) // get len args for rmdir lenArgs, _ := r.ReadByte() // only does something if more than "rmdir" is called, as above for i := 1; i < int(lenArgs); i++ { targetPath, _ := r.ReadString('\n') targetPath = strings.TrimSpace(targetPath) if !path.IsAbs(targetPath) { targetPath = path.Join(currentDir, targetPath) } fmt.Printf("\tUser %d called rmdir on: \"%s\"\n", uuid, targetPath) // this will only remove a dir that is empty, else it does nothing // BUG-NOTE: this command will also currently delete files (there is not // a different command to rmdir an rm in golang), so a check to make sure // the targetPath is a dir should take place (sample code for checking if // a path is a dir or a file is found in "cd" below). // NOTE: a nice to have would be a recursive remove similar to rm -rf, // but this is not needed src, err := os.Stat(md.getPath() + "files" + targetPath) hidden := utils.IsHidden(targetPath) if hidden { fmt.Printf("\tCall to hidden filepath \"%s\" is not permitted\n", targetPath) } if !hidden && err == nil && src.IsDir() && checkBase(uuid, targetPath, "w", md) { fi, _ := ioutil.ReadDir(md.getPath() + "files" + targetPath) if len(fi) == 1 { os.Remove(md.getPath() + "files" + targetPath + "/.perm") } os.Remove(md.getPath() + "files" + targetPath) } } return nil }
func mkdir(uuid uint64, conn net.Conn, r *bufio.Reader, w *bufio.Writer, md *MDService) (err error) { // get currentDir currentDir, _ := r.ReadString('\n') currentDir = strings.TrimSpace(currentDir) // get lenArgs for mkdir lenArgs, _ := r.ReadByte() // if no more than "mkdir" is sent, nothing will happen // if errors occur, the dir will just not be made for i := 1; i < int(lenArgs); i++ { // for each arg, get the target path targetPath, _ := r.ReadString('\n') targetPath = strings.TrimSpace(targetPath) if !path.IsAbs(targetPath) { targetPath = path.Join(currentDir, targetPath) } fmt.Printf("\tUser %d called mkdir \"%s\"\n", uuid, targetPath) hidden := utils.IsHidden(targetPath) if hidden { fmt.Printf("\tCall to hidden filepath \"%s\" is not permitted\n", targetPath) } if !hidden && checkBase(uuid, targetPath, "w", md) { os.Mkdir(md.getPath()+"files"+targetPath, 0777) permissions := []bool{false, false, false, false, false, false} var groups []uint64 err := createPerm(md.getPath()+"files"+targetPath, uuid, groups, permissions) if err != nil { return err } } } return nil }
func request(uuid uint64, conn net.Conn, r *bufio.Reader, w *bufio.Writer, md *MDService) (err error) { //get currentDir currentDir, _ := r.ReadString('\n') currentDir = strings.TrimSpace(currentDir) // receive filename from client filename, _ := r.ReadString('\n') filename = strings.TrimSpace(filename) // Cleans the filepath for proper access use if !path.IsAbs(filename) { filename = path.Join(currentDir, filename) } fmt.Printf("\tUser %d called request on: \"%s\"\n", uuid, currentDir+filename) // check if the filename exists src, err := os.Stat(md.getPath() + "files" + filename) hidden := utils.IsHidden(filename) if hidden { fmt.Printf("\tCall to hidden filepath \"%s\" is not permitted\n", filename) } if err != nil || hidden { // not a path ie. not a dir OR a file fmt.Println("\tFile \"" + filename + "\" does not exist") // notify the client that it is not existant with code "2" w.WriteByte(1) w.Flush() return nil } else if src.IsDir() { // notify the client that the file exists with code "1" fmt.Println("\tPath \"" + filename + "\" is a directory") // notify that is a dir w.WriteByte(2) w.Flush() return nil } else if !checkFile(uuid, filename, "x", md) { fmt.Println("\tUnauthorised access to request file") w.WriteByte(3) w.Flush() return nil } else { fmt.Println("\tFile \"" + filename + "\" exists") // notify success w.WriteByte(4) w.Flush() } hash, unid, protected, _, _, _, err := getFile(md.getPath() + "files" + filename) if protected { w.WriteByte(1) w.Flush() } else { w.WriteByte(2) w.Flush() } md.stnodeDB.View(func(tx *bolt.Tx) error { // Assume bucket exists and has keys b := tx.Bucket([]byte("stnodes")) v := b.Get([]byte(unid)) if v == nil { fmt.Println("\tNo stnode matching UNID: " + unid) w.WriteByte(1) w.Flush() return nil } w.WriteByte(2) w.Flush() var tmpStnode utils.Stnode json.Unmarshal(v, &tmpStnode) fmt.Println("\tGot details for stnode: protocol: " + tmpStnode.Protocol + ", address: " + tmpStnode.NAddress) w.WriteString(hash + "\n") w.WriteString(tmpStnode.Protocol + "\n") w.WriteString(tmpStnode.NAddress + "\n") w.Flush() return nil }) return nil }
func cd(uuid uint64, conn net.Conn, r *bufio.Reader, w *bufio.Writer, md *MDService) (err error) { // get current dir and target path currentDir, _ := r.ReadString('\n') targetPath, _ := r.ReadString('\n') currentDir = strings.TrimSpace(currentDir) targetPath = strings.TrimSpace(targetPath) if !path.IsAbs(targetPath) { targetPath = path.Join(currentDir, targetPath) } fmt.Printf("\tUser %d called cd \"%s\"\n", uuid, targetPath) // check if the source dir exist src, err := os.Stat(md.getPath() + "files" + targetPath) hidden := utils.IsHidden(targetPath) if hidden { fmt.Printf("\tCall to hidden filepath \"%s\" is not permitted\n", targetPath) } if err != nil || hidden { // not a path ie. not a dir OR a file fmt.Println("\tPath is not a directory") // notify the client that it is not a dir with error code "1" w.WriteByte(1) w.Flush() } else { // is a path, but is it a dir or a file? // check if the source is indeed a directory or not if !src.IsDir() { fmt.Println("\tPath is not a directory") // notify the client that it is not a dir with error code "1" w.WriteByte(1) w.Flush() } else if !checkEntry(uuid, targetPath, "x", md) { // success! fmt.Println("\tAccess denied to dir " + targetPath) // notify success to client (no specific code, just not 1 or 0) w.WriteByte(2) w.Flush() } else { // create a clean path that the user can display on the cmd line fmt.Printf("\tPath \"%s\" is a directory\n", targetPath) w.WriteByte(3) w.Flush() // send the new path back to the user w.WriteString(targetPath + "\n") w.Flush() } } return nil }
// Case commands for Mdserv func ls(uuid uint64, conn net.Conn, r *bufio.Reader, w *bufio.Writer, md *MDService) (err error) { // get current dir // NOTE: here and in other locations, trimming whitespace may be more desirable currentDir, _ := r.ReadString('\n') currentDir = strings.TrimSpace(currentDir) // get the length of arguments to the ls command inArgs, _ := r.ReadByte() lenArgs := int(inArgs) verbose, _ := r.ReadByte() if verbose == 1 { lenArgs = lenArgs - 1 fmt.Printf("\tUser %d called verbose ls\n", uuid) } // the message which will be returned to the user, each entry will be // comma separated for the client to interpret if lenArgs == 1 { fmt.Printf("\tUser %d called ls on: \"%s\"\n", uuid, currentDir) } // if only the ls command was called if lenArgs == 1 && checkEntry(uuid, currentDir, "r", md) { files, err := ioutil.ReadDir(md.getPath() + "files" + currentDir) if err != nil { w.Flush() } if currentDir == "/" || currentDir == "" { w.WriteByte(uint8(len(files))) w.Flush() } else { w.WriteByte(uint8(len(files) - 1)) w.Flush() } // iterate over the files, and comma separate them while appending to msg for _, file := range files { if !utils.IsHidden(file.Name()) { targetPath := path.Join(currentDir, file.Name()) prefix := "" ownerStr := "" if verbose == 1 { src, err := os.Stat(md.getPath() + "files" + targetPath) if err == nil && !src.IsDir() { //fmt.Println("Looking for path: " + md.getPath() + "files" + path.Join(currentDir, file.Name())) _, _, _, owner, _, permissions, err := getFile(md.getPath() + "files" + path.Join(currentDir, file.Name())) //fmt.Printf("filestats: %d, %v, %v\n", owner, groups, permissions) if err != nil { fmt.Println("\t\tError finding .permissions for path: " + path.Join(currentDir, file.Name())) return nil } //fmt.Printf("File read stats %v\n", permissions) ownerStr = " " + strconv.FormatUint(owner, 10) prefix = "-" for _, b := range permissions { if b { prefix = prefix + "r--" } else { prefix = prefix + "---" } } } else if err == nil && src.IsDir() { //fmt.Println("Looking for path: " + md.getPath() + "files" + path.Join(currentDir, file.Name(), ".perm")) owner, _, permissions, err := getPerm(path.Join(md.getPath(), "files", currentDir, file.Name())) if err != nil { fmt.Println("\t\tError finding .permissions for path: " + path.Join(currentDir, file.Name())) return nil } else { ownerStr = " " + strconv.FormatUint(owner, 10) prefix = "d" for i, b := range permissions { if b && i%3 == 0 { prefix = prefix + "r" } else if b && i%3 == 1 { prefix = prefix + "w" } else if b && i%3 == 2 { prefix = prefix + "x" } else { prefix = prefix + "-" } } } } prefix = prefix + ownerStr + "\t" } //fmt.Printf("Writing %d of %d = %s\n", i, len(files), file.Name()) w.WriteString(prefix + file.Name() + "\n") w.Flush() } } return nil } else if lenArgs == 1 { w.WriteByte(0) w.Flush() return nil } // loop for dealing with one or more args for j := 1; j < lenArgs; j++ { // reading in this arg targetPath, _ := r.ReadString('\n') targetPath = strings.TrimSpace(targetPath) if !path.IsAbs(targetPath) { targetPath = path.Join(currentDir, targetPath) } fmt.Printf("\tUser %d called ls on: \"%s\"\n", uuid, targetPath) files, err := ioutil.ReadDir(md.getPath() + "files" + targetPath) if err != nil { hidden := utils.IsHidden(targetPath) if hidden { fmt.Printf("\tCall to hidden filepath \"%s\" is not permitted\n", targetPath) } // if it is not a directory, skip it and try the next arg w.WriteByte(0) w.Flush() continue } else if checkEntry(uuid, targetPath, "r", md) { if targetPath == "/" || targetPath == "" { w.WriteByte(uint8(len(files) + 1)) w.Flush() } else { // fmt.Printf("Num writes = %d\n", len(files)) w.WriteByte(uint8(len(files))) w.Flush() } // fmt.Println("Writing header: " + targetPath + ":") w.WriteString(targetPath + ":" + "\n") w.Flush() for _, file := range files { if !utils.IsHidden(file.Name()) { prefix := "" ownerStr := "" if verbose == 1 { src, err := os.Stat(md.getPath() + "files" + targetPath + "/" + file.Name()) // fmt.Println("IN VERBOSE: " + md.getPath() + "files" + targetPath + file.Name()) if err == nil && !src.IsDir() { // fmt.Println("Looking for file1 path: " + md.getPath() + "files" + path.Join(targetPath, file.Name())) _, _, _, owner, _, permissions, err := getFile(md.getPath() + "files" + path.Join(targetPath, file.Name())) if err != nil { fmt.Println("\t\tError finding .permissions for path: " + path.Join(targetPath, file.Name())) break } ownerStr = " " + strconv.FormatUint(owner, 10) prefix = "-" for _, b := range permissions { if b { prefix = prefix + "r--" } else { prefix = prefix + "---" } } } else if err == nil && src.IsDir() { // fmt.Println("Looking for perm1 path: " + md.getPath() + "files" + path.Join(targetPath, file.Name(), ".perm")) owner, _, permissions, err := getPerm(md.getPath() + "files" + path.Join(targetPath, file.Name())) if err != nil { fmt.Println("\t\tError finding .permissions for path: " + path.Join(targetPath, file.Name())) break } else { ownerStr = " " + strconv.FormatUint(owner, 10) prefix = "d" for i, b := range permissions { if b && i%3 == 0 { prefix = prefix + "r" } else if b && i%3 == 1 { prefix = prefix + "w" } else if b && i%3 == 2 { prefix = prefix + "x" } else { prefix = prefix + "-" } } } } prefix = prefix + ownerStr + "\t" } // fmt.Printf("Writing %d of %d = %s = %s\n", i, len(files), file.Name(), prefix) w.WriteString(prefix + file.Name() + "\n") w.Flush() } } } else { w.WriteByte(0) w.Flush() } } // print for terminal's sake return nil }
func send(uuid uint64, conn net.Conn, r *bufio.Reader, w *bufio.Writer, md *MDService) (err error) { // get current dir currentDir, _ := r.ReadString('\n') currentDir = strings.TrimSpace(currentDir) // receive filename from client filename, _ := r.ReadString('\n') filename = strings.TrimSpace(filename) // clean the path if !path.IsAbs(filename) { filename = path.Join(currentDir, filename) } fmt.Printf("\tUser %d called send to \"%s\"\n", uuid, currentDir+filename) // check if the filename exists already _, err = os.Stat(md.getPath() + "files" + filename) hidden := utils.IsHidden(filename) if hidden { fmt.Printf("\tCall to hidden filepath \"%s\" is not permitted\n", filename) } if !checkBase(uuid, filename, "w", md) { fmt.Println("\tUser does not have permission to send to this directory.") w.WriteByte(3) w.Flush() return nil } else if err != nil && !hidden { // not a path ie. not a dir OR a file fmt.Println("\tFile \"" + filename + "\" does not already exist here") // notify the client that it is not already on system w.WriteByte(2) w.Flush() } else { // notify the client that the file exists with error code "1" fmt.Println("\tFile already exists in this directory") w.WriteByte(1) w.Flush() return nil } // is the user encrypting the file? protected := false enc, _ := r.ReadByte() if enc == 1 { // we are encrypting protected = true fmt.Println("\tReceiving encrypted file") // send the pubkeys of users here // get lenArgs lenArgs, _ := r.ReadByte() for i := 0; i < int(lenArgs); i++ { md.userDB.View(func(tx *bolt.Tx) error { b := tx.Bucket([]byte("users")) // get the proposed uuid for a user tmpUuid, _ := r.ReadString('\n') tmpUuid = strings.TrimSpace(tmpUuid) uuidUint64, _ := strconv.ParseUint(tmpUuid, 10, 64) v := b.Get(itob(uuidUint64)) if v == nil { fmt.Println("\tNo user profile matching UUID: " + tmpUuid) w.WriteString("INV" + "\n") w.Flush() return nil } var tmpUser utils.User json.Unmarshal(v, &tmpUser) fmt.Println("\tFound user: "******"\n") w.Write([]byte(tmpUser.Pubkey.N.String() + "\n")) w.Write([]byte(strconv.Itoa(tmpUser.Pubkey.E) + "\n")) w.Flush() return nil }) } } else if enc == 2 { //invalid cmd on client side return nil // else we are not } // get the hash of the file hash := utils.ReadHashAsString(r) var success byte var unid string md.stnodeDB.View(func(tx *bolt.Tx) error { // Assume bucket exists and has keys b := tx.Bucket([]byte("stnodes")) c := b.Cursor() for k, v := c.First(); k != nil; k, v = c.Next() { w.WriteByte(1) // got a stnode w.Flush() var tmpStnode utils.Stnode json.Unmarshal(v, &tmpStnode) fmt.Println("\tGot details for stnode: protocol: " + tmpStnode.Protocol + ", address: " + tmpStnode.NAddress) w.WriteString(tmpStnode.Protocol + "\n") w.WriteString(tmpStnode.NAddress + "\n") unid = tmpStnode.Unid w.Flush() success, _ = r.ReadByte() if success != 1 { fmt.Println("\tSuccessful send to stnode from client") return nil } } w.WriteByte(2) // no more stnodes w.Flush() return nil }) if success != 2 { fmt.Println("\tNo stnodes were available to the client") return nil } success, _ = r.ReadByte() if success != 1 { fmt.Println("\tError on client side sending file to stnode") return nil } permissions := []bool{false, false} var groups []uint64 err = createFile(md.getPath()+"files"+filename, hash, unid, protected, uuid, groups, permissions) if err != nil { panic(err) } return nil }
func deny(uuid uint64, conn net.Conn, r *bufio.Reader, w *bufio.Writer, md *MDService) (err error) { currentDir, _ := r.ReadString('\n') currentDir = strings.TrimSpace(currentDir) flag, _ := r.ReadString('\n') flag = strings.TrimSpace(flag) if flag == "INV" { fmt.Printf("\t\tInvalid flag from user %d\n", uuid) return nil } lenArgs, _ := r.ReadByte() targetPath, _ := r.ReadString('\n') targetPath = strings.TrimSpace(targetPath) if !path.IsAbs(targetPath) { targetPath = path.Join(currentDir, targetPath) } fmt.Printf("\tUser %d called deny %s on: \"%s\"\n", uuid, flag, targetPath) src, err := os.Stat(md.getPath() + "files" + targetPath) if err != nil || utils.IsHidden(targetPath) { // exists, not hidden path fmt.Printf("\tUser %d call to deny %s on: \"%s\" was invalid: target does not exist\n", uuid, flag, targetPath) return nil } var groups []uint64 if src.IsDir() { addPerms, _ := r.ReadString('\n') addPerms = strings.TrimSpace(addPerms) for i := 4; i < int(lenArgs); i++ { group, _ := r.ReadString('\n') gid, err := strconv.ParseUint(strings.TrimSpace(group), 10, 64) if err != nil { continue } groups = append(groups, gid) } if checkEntry(uuid, targetPath, "owner", md) { owner, existingGroups, permissions, err := getPerm(md.getPath() + "files" + targetPath) if err != nil { fmt.Println("\t\tError: no .perm file exists at \"" + md.getPath() + "files" + targetPath + "/.perm\"") return nil } switch flag { case "-g": fmt.Printf("\tDenying groups ") for _, g := range groups { for i, gr := range existingGroups { if g == gr { existingGroups = append(existingGroups[:i], existingGroups[i+1:]...) fmt.Printf("%d, ", g) break } } } fmt.Print("for: ") if strings.Contains(addPerms, "r") { permissions[0] = false fmt.Print("r") } if strings.Contains(addPerms, "w") { permissions[1] = false fmt.Print("w") } if strings.Contains(addPerms, "x") { permissions[2] = false fmt.Print("x") } fmt.Println(" to " + targetPath) case "-w": fmt.Printf("\tDenying world for: ") if strings.Contains(addPerms, "r") { permissions[3] = false fmt.Print("r") } if strings.Contains(addPerms, "w") { permissions[4] = false fmt.Print("w") } if strings.Contains(addPerms, "x") { permissions[5] = false fmt.Print("x") } fmt.Println(" to " + targetPath) } err = createPerm(md.getPath()+"files"+targetPath, owner, existingGroups, permissions) if err != nil { fmt.Println("\t\tError: there was an issue setting .perm for \"" + md.getPath() + "files" + targetPath + "/.perm\"\n\t\tCould not set new permissions") } } } else { for i := 3; i < int(lenArgs); i++ { group, _ := r.ReadString('\n') gid, err := strconv.ParseUint(strings.TrimSpace(group), 10, 64) if err != nil { continue } groups = append(groups, gid) } if checkFile(uuid, targetPath, "x", md) { hash, stnode, protected, owner, existingGroups, permissions, err := getFile(md.getPath() + "files" + targetPath) if err != nil { fmt.Println("\t\tError: no permissions could be read for file: \"" + md.getPath() + "files" + targetPath + "\"\n\t\tCould not set new permissions") return nil } switch flag { case "-g": fmt.Printf("\tDenying groups ") for _, g := range groups { for i, gr := range existingGroups { if g == gr { existingGroups = append(existingGroups[:i], existingGroups[i+1:]...) fmt.Printf("%d, ", g) break } } } fmt.Println("for request access to " + targetPath) permissions[0] = false case "-w": fmt.Println("\tDenying world for request access to " + targetPath) permissions[1] = false } err = createFile(md.getPath()+"files"+targetPath, hash, stnode, protected, owner, existingGroups, permissions) if err != nil { fmt.Println("\t\tError re-writing permissions for file: " + targetPath) } } } return nil }