Skip to content

Commit

Permalink
Improve API and security
Browse files Browse the repository at this point in the history
Switch `[]string` to `string...` in ai.AddFiles... etc, now copy over
AppImage's profile to the system to prevent an AppImage from modifying
its own permissions, add Open-typer and Cro-Mag Rally to supported
profiles and add FreeCAD Weekly as an an alias
  • Loading branch information
mgord9518 committed Aug 13, 2022
1 parent faf7a35 commit d4c35eb
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 40 deletions.
68 changes: 53 additions & 15 deletions appimage.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package aisap

import (
"bufio"
"crypto/md5"
"debug/elf"
"fmt"
Expand All @@ -20,6 +21,7 @@ import (
profiles "github.com/mgord9518/aisap/profiles"
permissions "github.com/mgord9518/aisap/permissions"
squashfs "github.com/CalebQ42/squashfs"
xdg "github.com/adrg/xdg"
)

type AppImage struct {
Expand All @@ -44,7 +46,7 @@ type AppImage struct {

// Current version of aisap
const (
Version = "0.7.3-alpha"
Version = "0.7.5-alpha"
)

// Create a new AppImage object from a path
Expand All @@ -63,7 +65,6 @@ func NewAppImage(src string) (*AppImage, error) {
if err != nil { return nil, err }

ai.rootDir = "/"

ai.Offset, err = helpers.GetOffset(src)
if err != nil { return nil, err }

Expand All @@ -80,7 +81,12 @@ func NewAppImage(src string) (*AppImage, error) {
}

// Prefer local entry if it exists (located at $XDG_DATA_HOME/aisap/[ai.Name])
ai.Desktop, err = ai.getEntry()
desktopReader, err := ai.getEntry()
if err != nil { return ai, err }

ai.Desktop, err = ini.LoadSources(ini.LoadOptions{
IgnoreInlineComment: true,
}, desktopReader)
if err != nil { return ai, err }

ai.Name = ai.Desktop.Section("Desktop Entry").Key("Name").Value()
Expand All @@ -92,6 +98,7 @@ func NewAppImage(src string) (*AppImage, error) {
ai.Version = "1.0"
}


// If PREFER_AISAP_PROFILE is set, attempt to use it over the AppImage's
// suggested permissions. If no profile exists in aisap, fall back on saved
// permissions in aisap, and then finally the AppImage's internal desktop
Expand All @@ -110,8 +117,25 @@ func NewAppImage(src string) (*AppImage, error) {
}
}

// Fall back to permissions inside AppImage if all else fails
if err != nil {
ai.Perms, _ = permissions.FromIni(ai.Desktop)

// Copy AppImage permissions to system to prevent an AppImage from
// modifying its own permissions through an update. This also gives
// users a good template to customize their permissions on a per-app
// basis.
aisapConfig := filepath.Join(xdg.DataHome, "aisap", "profiles")
if !helpers.DirExists(aisapConfig) {
os.MkdirAll(aisapConfig, 0744)
}

filePath := filepath.Join(aisapConfig, ai.Name)
if !helpers.FileExists(filePath) {
desktopReader, _ = ai.getEntry()
permFile, _ := os.Create(filePath)
io.Copy(permFile, desktopReader)
}
}

return ai, nil
Expand Down Expand Up @@ -265,9 +289,9 @@ func (ai *AppImage) Icon() (io.ReadCloser, string, error) {
}

// Extract the desktop file from the AppImage
func (ai *AppImage) getEntry() (*ini.File, error) {
func (ai *AppImage) getEntry() (io.Reader, error) {
var r io.Reader
var err error
var r io.ReadCloser

if ai.imageType == -2 {
r, err = helpers.ExtractResourceReader(ai.Path, "desktop_entry")
Expand All @@ -283,14 +307,10 @@ func (ai *AppImage) getEntry() (*ini.File, error) {
return nil, NoDesktopFile
}

r, err = ai.reader.Open(fp[0])
defer r.Close()
if err != nil { return nil, err }
return ai.reader.Open(fp[0])
}

return ini.LoadSources(ini.LoadOptions{
IgnoreInlineComment: true,
}, r)
return r, err
}

// Determine what architectures a bundle supports
Expand Down Expand Up @@ -320,10 +340,28 @@ func (ai *AppImage) getArchitectures() ([]string, error) {
}

// Assume arch via shImg runtime
// TODO: implement
//if ai.Type() < -1 {

//}
if ai.Type() < -1 {
scanner := bufio.NewScanner(ai.file)
arches := []string{}

counter := 0
for scanner.Scan() {
counter++
if strings.HasPrefix(scanner.Text(), "arch='") {
str := scanner.Text()
str = strings.ReplaceAll(str, "arch='", "")
str = strings.ReplaceAll(str, "'", "")
arches = helpers.SplitKey(str)
return arches, nil
}

// All shImg info should be at the top of the file, 50 is more than
// enough
if counter >= 50 {
break
}
}
}

return s, errors.New("failed to determine arch")
}
12 changes: 6 additions & 6 deletions cmd/aisap/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,12 @@ func main() {
// Add (and remove) permissions as passed from flags. eg: `--add-file`
// Note: If *not* using XDG standard names (eg: `xdg-desktop`) you MUST
// Provide the full filepath when using `AddFiles`
ai.Perms.RemoveFiles(rmFile)
ai.Perms.RemoveDevices(rmDevice)
ai.Perms.RemoveSockets(rmSocket)
ai.Perms.AddFiles(addFile)
ai.Perms.AddDevices(addDevice)
ai.Perms.AddSockets(addSocket)
ai.Perms.RemoveFiles(rmFile...)
ai.Perms.RemoveDevices(rmDevice...)
ai.Perms.RemoveSockets(rmSocket...)
ai.Perms.AddFiles(addFile...)
ai.Perms.AddDevices(addDevice...)
ai.Perms.AddSockets(addSocket...)

// If the `--level` flag is used, set the AppImage to that level
if *level > -1 && *level <= 3 {
Expand Down
6 changes: 3 additions & 3 deletions helpers/offset.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ func getElfSize(src string) (int, error) {
sr := io.NewSectionReader(f, 0, 1<<63-1)
var shoff, shentsize, shnum int

switch e.Class.String() {
case "ELFCLASS64":
switch e.Class {
case elf.ELFCLASS64:
hdr := new(elf.Header64)

_, err = sr.Seek(0, 0)
Expand All @@ -81,7 +81,7 @@ func getElfSize(src string) (int, error) {
shoff = int(hdr.Shoff)
shnum = int(hdr.Shnum)
shentsize = int(hdr.Shentsize)
case "ELFCLASS32":
case elf.ELFCLASS32:
hdr := new(elf.Header32)

_, err = sr.Seek(0, 0)
Expand Down
6 changes: 3 additions & 3 deletions permissions/getperms.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ func FromIni(e *ini.File) (*AppImagePerms, error) {
}

// Split string into slices and clean up the names
p.AddFiles(helpers.SplitKey(filePerms))
p.AddDevices(helpers.SplitKey(devicePerms))
p.AddSockets(helpers.SplitKey(socketPerms))
p.AddFiles(helpers.SplitKey(filePerms)...)
p.AddDevices(helpers.SplitKey(devicePerms)...)
p.AddSockets(helpers.SplitKey(socketPerms)...)

return p, nil
}
Expand Down
18 changes: 9 additions & 9 deletions permissions/modifyperms.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ func (p *AppImagePerms) AddFile(str string) {
p.Files = append(p.Files, helpers.CleanFile(str))
}

func (p *AppImagePerms) AddFiles(s []string) {
func (p *AppImagePerms) AddFiles(s ...string) {
// Remove previous files of the same name if they exist
p.RemoveFiles(s)
p.RemoveFiles(s...)

p.Files = append(p.Files, helpers.CleanFiles(s)...)
}
Expand All @@ -27,8 +27,8 @@ func (p *AppImagePerms) AddDevice(str string) {
p.Devices = append(p.Devices, helpers.CleanDevice(str))
}

func (p *AppImagePerms) AddDevices(s []string) {
p.RemoveDevices(s)
func (p *AppImagePerms) AddDevices(s ...string) {
p.RemoveDevices(s...)

p.Devices = append(p.Devices, helpers.CleanDevices(s)...)
}
Expand All @@ -39,8 +39,8 @@ func (p *AppImagePerms) AddSocket(str string) {
p.Sockets = append(p.Sockets, str)
}

func (p *AppImagePerms) AddSockets(s []string) {
p.RemoveSockets(s)
func (p *AppImagePerms) AddSockets(s ...string) {
p.RemoveSockets(s...)

p.Sockets = append(p.Sockets, s...)
}
Expand All @@ -58,7 +58,7 @@ func (p *AppImagePerms) RemoveFile(str string) {
}
}

func (p *AppImagePerms) RemoveFiles(s []string) {
func (p *AppImagePerms) RemoveFiles(s ...string) {
for i := range(s) {
p.RemoveFile(s[i])
}
Expand All @@ -70,7 +70,7 @@ func (p *AppImagePerms) RemoveDevice(str string) {
}
}

func (p *AppImagePerms) RemoveDevices(s []string) {
func (p *AppImagePerms) RemoveDevices(s ...string) {
for i := range(s) {
p.RemoveDevice(s[i])
}
Expand All @@ -82,7 +82,7 @@ func (p *AppImagePerms) RemoveSocket(str string) {
}
}

func (p *AppImagePerms) RemoveSockets(s []string) {
func (p *AppImagePerms) RemoveSockets(s ...string) {
for i := range(s) {
p.RemoveSocket(s[i])
}
Expand Down
19 changes: 15 additions & 4 deletions profiles/profiles.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
// issue and any error messages you encounter so that I can try to fix them
// NOTE: Some app permissions are `aliases` of others, so care must be taken
// that modifying the parent permission will also affect apps based on it
// 90 unique apps currently supported
// 92 unique apps currently supported
var profiles = map[string]permissions.AppImagePerms{
"0 a.d.": {
Level: 3,
Expand Down Expand Up @@ -113,6 +113,11 @@ var profiles = map[string]permissions.AppImagePerms{
Devices: []string{ "dri" },
Sockets: []string{ "x11", "pid" },
},
"cro-mag rally": {
Level: 3,
Devices: []string{ "dri" },
Sockets: []string{ "x11", "alsa" },
},
"deemix-gui": {
Level: 2,
Devices: []string{ "dri" },
Expand Down Expand Up @@ -153,16 +158,16 @@ var profiles = map[string]permissions.AppImagePerms{
Files: []string{ "xdg-documents:rw", "xdg-publicshare:rw",
"xdg-templates:rw", "xdg-desktop:rw",
"xdg-documents:rw", "xdg-download:rw",
"xdg-music:rw", "xdg-videos:rw"},
"xdg-music:rw", "xdg-videos:rw" },
Sockets: []string{ "x11", "audio" },
},
"edex-ui": {
Level: 2,
Devices: []string{ "dri" },
Files: []string{ "~/.config/nvim:ro", "~/.profile:ro",
"~/.bashrc:ro", "~/.zshrc:ro",
"~/.viminfo:ro"},
Sockets: []string{ "x11", "network" },
"~/.viminfo:ro" },
Sockets: []string{ "x11", "network", "alsa" },
},
"element": {
Level: 2,
Expand Down Expand Up @@ -374,6 +379,11 @@ var profiles = map[string]permissions.AppImagePerms{
Devices: []string{ "dri" },
Sockets: []string{ "x11", "alsa" },
},
"open-typer": {
Level: 2,
Devices: []string{ "dri" },
Sockets: []string{ "x11" },
},
"passy": {
Level: 2,
Devices: []string{ "dri" },
Expand Down Expand Up @@ -565,6 +575,7 @@ func FromName(name string) (*permissions.AppImagePerms, error) {
"aranym mmu": "aranym jit",
"firefox beta": "firefox",
"firefox nightly": "firefox",
"freecad weekly": "freecad conda",
"python2.7.18": "python",
"python3": "python",
"python3.5.10": "python",
Expand Down

0 comments on commit d4c35eb

Please sign in to comment.