Exemple #1
0
func getPermissionsAsString(driveFile *gdrive.File) (string, error) {
	var str string
	if driveFile.IsFolder() {
		str = "d"
	} else {
		str = "-"
	}

	perm, err := getPermissions(driveFile)
	if err != nil {
		// No permissions are available if the file was uploaded via the
		// Drive Web page, for example.
		str += "?????????"
	} else {
		rwx := "rwx"
		for i := 0; i < 9; i++ {
			if perm&(1<<(8-uint(i))) != 0 {
				str += string(rwx[i%3])
			} else {
				str += "-"
			}
		}
	}
	return str, nil
}
Exemple #2
0
func getPermissions(driveFile *gdrive.File) (os.FileMode, error) {
	permStr, err := driveFile.GetProperty("Permissions")
	if err != nil {
		return 0, err
	}
	perm, err := strconv.ParseInt(permStr, 8, 16)
	return os.FileMode(perm), err
}
Exemple #3
0
// Returns the initialization vector (for encryption) for the given file.
// We store the initialization vector as a hex-encoded property in the
// file so that we don't need to download the file's contents to find the
// IV.
func getInitializationVector(driveFile *gdrive.File) ([]byte, error) {
	ivhex, err := driveFile.GetProperty("IV")
	if err != nil {
		return nil, err
	}
	iv, err := hex.DecodeString(ivhex)
	if err != nil {
		return nil, err
	}
	if len(iv) != aes.BlockSize {
		return nil, fmt.Errorf("unexpected length of IV %d", len(iv))
	}
	return iv, nil
}
Exemple #4
0
func checkFile(f *gdrive.File) int {
	hasSuffix := strings.HasSuffix(f.Path, encryptionSuffix)
	_, err := f.GetProperty("IV")
	hasIV := err == nil

	if hasSuffix && !hasIV {
		fmt.Fprintf(os.Stderr, "skicka: %s: has filename suffix \"%s\" but no IV property\n",
			f.Path, encryptionSuffix)
		return 1
	} else if hasIV && !hasSuffix {
		fmt.Fprintf(os.Stderr, "skicka: %s: has IV property but no filename suffix \"%s\"\n",
			f.Path, encryptionSuffix)
		return 1
	}
	return 0
}
Exemple #5
0
// If a file is encrypted, it should both have the initialization vector used
// to encrypt it stored as a Drive file property and have encryptionSuffix at the end
// of its filename. This function checks both of these and returns an error if
// these indicators are inconsistent; otherwise, it returns true/false
// accordingly.
func isEncrypted(file *gdrive.File) (bool, error) {
	if _, err := file.GetProperty("IV"); err == nil {
		if strings.HasSuffix(file.Path, encryptionSuffix) {
			return true, nil
		}
		return false, fmt.Errorf("has IV property but doesn't " +
			"end with .aes256 suffix")
	} else if strings.HasSuffix(file.Path, encryptionSuffix) {
		// This could actually happen with an interrupted upload
		// with 403 errors and the case where a file is created
		// even though a 403 happened, if we don't get to delete
		// the file before exiting...
		return false, fmt.Errorf("ends with .aes256 suffix but doesn't " +
			"have IV property")
	}
	return false, nil
}
Exemple #6
0
// Produce listing output to stdout for a single file.
func lsFile(f *gdrive.File, recursive, long, longlong bool) {
	printFilename := f.Path
	if !recursive {
		printFilename = filepath.Base(printFilename)
	}
	if f.IsFolder() {
		printFilename += string(os.PathSeparator)
	}

	if !long && !longlong {
		fmt.Printf("%s\n", printFilename)
		return
	}

	synctime := f.ModTime
	permString, _ := getPermissionsAsString(f)
	if longlong {
		md5 := f.Md5
		if len(md5) != 32 {
			md5 = "--------------------------------"
		}
		fmt.Printf("%s  %s  %s  %s  %s\n", permString,
			fmtbytes(f.FileSize, true), md5, synctime.Format(time.ANSIC),
			printFilename)
		if debug {
			fmt.Printf("\t[ ")
			for _, prop := range f.Properties {
				fmt.Printf("%s: %s, ", prop.Key, prop.Value)
			}
			fmt.Printf("MimeType: %s, ", f.MimeType)
			fmt.Printf("id: %s ]\n", f.Id)
		}
	} else {
		fmt.Printf("%s  %s  %s  %s\n", permString, fmtbytes(f.FileSize, true),
			synctime.Format(time.ANSIC), printFilename)
	}
}
Exemple #7
0
// If we didn't shut down cleanly before, there may be files that
// don't have the various properties we expect. Check for that now
// and patch things up as needed.
func createMissingProperties(f *gdrive.File, mode os.FileMode, encrypt bool) error {
	if !f.IsFolder() && encrypt {
		if _, err := f.GetProperty("IV"); err != nil {
			if f.FileSize == 0 {
				// Compute a unique IV for the file.
				iv := getRandomBytes(aes.BlockSize)
				ivhex := hex.EncodeToString(iv)

				debug.Printf("Creating IV property for file %s, "+
					"which doesn't have one.", f.Path)
				err := gd.AddProperty("IV", ivhex, f)
				if err != nil {
					return err
				}
			} else {
				// This is state of affairs really shouldn't ever happen, but
				// if somehow it does, it's important that we catch it: the
				// file is missing the IV property, but has some
				// contents. Presumably the IV is at the start of the file
				// contents and we could initialize the property from that
				// here, but any successfully created file should already have
				// the property, so we'll just error out, since it's not clear
				// what's going on here...
				return fmt.Errorf("encrypted file on Drive is missing" +
					"IV property, but has non-zero length. Can't create the IV " +
					"property without examining file contents.")
			}
		}
	}
	if _, err := f.GetProperty("Permissions"); err != nil {
		debug.Printf("Creating Permissions property for file %s, "+
			"which doesn't have one.", f.Path)
		err := gd.AddProperty("Permissions", fmt.Sprintf("%#o", mode&os.ModePerm), f)
		if err != nil {
			return err
		}
	}
	return nil
}