Skip to content

Commit

Permalink
Added valid-shell command.
Browse files Browse the repository at this point in the history
  • Loading branch information
nao1215 committed Dec 17, 2021
1 parent b226592 commit 4514ae4
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file. The format
- remove-shell command.
- reset command.
- sync command.
- valid-shell command.
### Changed
- Project
- the classification of directories under internal/applets.
Expand Down
1 change: 1 addition & 0 deletions docs/introduction/en/CommandAppletList.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
| unexpand| Convert N space to TAB (default:N=8)|
| unix2dos| Change LF to CRLF|
| uuidgeb| Print UUID (Universal Unique IDentifier|
| valid-shell| Verify if /etc/shells is valid|
| wc | Word Counter|
| wget | The non-interactive network downloader|
| which | Returns the file path which would be executed in the current environment|
Expand Down
2 changes: 2 additions & 0 deletions internal/applets/applet.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import (
"github.com/nao1215/mimixbox/internal/applets/mbutils/path"
"github.com/nao1215/mimixbox/internal/applets/mbutils/sddf"
"github.com/nao1215/mimixbox/internal/applets/mbutils/serial"
validShell "github.com/nao1215/mimixbox/internal/applets/mbutils/valid-shell"
"github.com/nao1215/mimixbox/internal/applets/shellutils/base64"
"github.com/nao1215/mimixbox/internal/applets/shellutils/basename"
"github.com/nao1215/mimixbox/internal/applets/shellutils/chroot"
Expand Down Expand Up @@ -148,6 +149,7 @@ func init() {
"unexpand": {unexpand.Run, "Convert N space to TAB(default:N=8)"},
"unix2dos": {unix2dos.Run, "Change LF to CRLF"},
"uuidgen": {uuidgen.Run, "Print UUID (Universal Unique IDentifier"},
"valid-shell": {validShell.Run, "Verify if /etc/shells is valid"},
"wc": {wc.Run, "Word Count"},
"wget": {wget.Run, "The non-interactive network downloader"},
"which": {which.Run, "Returns the file path which would be executed in the current environment"},
Expand Down
168 changes: 168 additions & 0 deletions internal/applets/mbutils/valid-shell/valid-shell.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
//
// mimixbox/internal/applets/debianutils/valid-shell/valid-shell.go
//
// Copyright 2021 Naohiro CHIKAMATSU
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package validShell

import (
"fmt"
"os"
"os/exec"
"strings"

"github.com/jessevdk/go-flags"
mb "github.com/nao1215/mimixbox/internal/lib"
)

const cmdName string = "valid-shell"

const version = "1.0.0"

var osExit = os.Exit

type options struct {
Show bool `short:"s" long:"show" description:"Print contents of /etc/shells"`
Fix bool `short:"f" long:"fix" description:"Fix problems in /etc/shells"`
Version bool `short:"v" long:"version" description:"Show valid-shell command version"`
}

// Exit code
const (
ExitSuccess int = iota // 0
ExitFailuer
)

func Run() (int, error) {
var opts options
var err error

if _, err = parseArgs(&opts); err != nil {
return ExitFailuer, nil
}

return validShell(opts)
}

func validShell(opts options) (int, error) {
if opts.Show {
return printShellsFile()
} else if opts.Fix {
return fix()
}
return valid()
}

func printShellsFile() (int, error) {
lines, err := mb.ReadFileToStrList(mb.ShellsFilePath)
if err != nil {
return ExitFailuer, err
}
for _, v := range lines {
fmt.Fprintf(os.Stdout, "%s", v)
}
return ExitSuccess, nil
}

func fix() (int, error) {
f, err := os.OpenFile(mb.TmpShellsFile(), os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return ExitFailuer, err
}
defer f.Close()

lines, err := mb.ReadFileToStrList(mb.ShellsFilePath)
if err != nil {
return ExitFailuer, err
}

lines = mb.ChopAll(lines)
for _, v := range lines {
if strings.HasPrefix(v, "#") {
fmt.Fprintln(f, v)
continue
}
if isFalseCmd(v) {
continue // NG: Bupass
}
if mb.Exists(v) {
fmt.Fprintln(f, v)
} // else is NG: Bypass
}

err = mb.Copy(mb.TmpShellsFile(), mb.ShellsFilePath)
if err != nil {
mb.RemoveFile(mb.TmpShellsFile(), false)
return ExitFailuer, err
}
mb.RemoveFile(mb.TmpShellsFile(), false)

return ExitSuccess, nil
}

func valid() (int, error) {
lines, err := mb.ReadFileToStrList(mb.ShellsFilePath)
if err != nil {
return ExitFailuer, err
}

lines = mb.ChopAll(lines)
for _, v := range lines {
if strings.HasPrefix(v, "#") {
continue
}
if isFalseCmd(v) {
fmt.Fprintf(os.Stdout, "NG: %s (not preferable for security)\n", v)
continue
}
if mb.Exists(v) {
fmt.Fprintf(os.Stdout, "OK: %s\n", v)
} else {
fmt.Fprintf(os.Stdout, "NG: %s (not exist in the system)\n", v)
}
}
return ExitSuccess, nil
}

func isFalseCmd(str string) bool {
path, err := exec.LookPath("false")
if err != nil {
return false
}
return path == str
}

func parseArgs(opts *options) ([]string, error) {
p := initParser(opts)

args, err := p.Parse()
if err != nil {
return nil, err
}

if opts.Version {
mb.ShowVersion(cmdName, version)
osExit(ExitSuccess)
}

return args, nil
}

func initParser(opts *options) *flags.Parser {
parser := flags.NewParser(opts, flags.Default)
parser.Name = cmdName
parser.Usage = "[OPTIONS]"

return parser
}

0 comments on commit 4514ae4

Please sign in to comment.