github.com/tommi2day/gomodules@v1.13.2-0.20240423190010-b7d55d252a27/pwlib/get_password.go (about) 1 package pwlib 2 3 import ( 4 "errors" 5 "fmt" 6 "os" 7 "strings" 8 9 "github.com/tommi2day/gomodules/common" 10 11 log "github.com/sirupsen/logrus" 12 ) 13 14 // Methods all available methods for get_passwword 15 var Methods = []string{typeGO, typeOpenssl, typeEnc, typePlain, typeVault, typeGPG, typeGopass, typeKMS} 16 17 // DecryptFile decripts an rsa protected file 18 func (pc *PassConfig) DecryptFile() (lines []string, err error) { 19 cryptedfile := pc.CryptedFile 20 privatekeyfile := pc.PrivateKeyFile 21 keypass := pc.KeyPass 22 datadir := pc.DataDir 23 sessionpassfile := pc.SessionPassFile 24 passflag := "open" 25 content := "" 26 method := pc.Method 27 keyID := pc.KMSKeyID 28 var data []byte 29 if len(keypass) > 0 { 30 passflag = "Encypted" 31 } 32 log.Debugf("Decrypt data from %s with method %s(%s)", cryptedfile, method, passflag) 33 34 switch method { 35 case typeOpenssl: 36 content, err = PrivateDecryptFileSSL(cryptedfile, privatekeyfile, keypass, sessionpassfile) 37 case typeGO: 38 content, err = PrivateDecryptFileGo(cryptedfile, privatekeyfile, keypass) 39 case typeEnc: 40 data, err = DecodeFile(cryptedfile) 41 content = string(data) 42 case typePlain: 43 //nolint gosec 44 data, err = os.ReadFile(cryptedfile) 45 content = string(data) 46 case typeVault: 47 content, err = GetVaultSecret(cryptedfile, "", "") 48 case typeGPG: 49 content, err = GPGDecryptFile(cryptedfile, privatekeyfile, keypass, "") 50 case typeGopass: 51 content, err = GetGopassSecrets(datadir, privatekeyfile, keypass) 52 case typeKMS: 53 content, err = KMSDecryptFile(cryptedfile, keyID, sessionpassfile) 54 default: 55 log.Fatalf("encryption method %s not known", method) 56 os.Exit(1) 57 } 58 59 if err != nil { 60 log.Debug("load data failed") 61 return 62 } 63 content = strings.ReplaceAll(content, "\r", "") 64 lines = strings.Split(content, "\n") 65 log.Debug("load data success") 66 return 67 } 68 69 // EncryptFile encrypt plain text to rsa protected file 70 func (pc *PassConfig) EncryptFile() (err error) { 71 cryptedFile := pc.CryptedFile 72 pubKeyFile := pc.PubKeyFile 73 plaintextfile := pc.PlainTextFile 74 sessionpassfile := pc.SessionPassFile 75 method := pc.Method 76 keyID := pc.KMSKeyID 77 log.Debugf("Encrypt data from %s method %s", plaintextfile, method) 78 switch method { 79 case typeOpenssl: 80 err = PubEncryptFileSSL(plaintextfile, cryptedFile, pubKeyFile, sessionpassfile) 81 case typeGO: 82 err = PubEncryptFileGo(plaintextfile, cryptedFile, pubKeyFile) 83 case typeEnc: 84 err = EncodeFile(plaintextfile, cryptedFile) 85 case typePlain: 86 // no need to do anything 87 err = nil 88 case typeGPG: 89 err = GPGEncryptFile(plaintextfile, cryptedFile, pubKeyFile) 90 case typeKMS: 91 err = KMSEncryptFile(plaintextfile, cryptedFile, keyID, sessionpassfile) 92 case typeVault, typeGopass: 93 // not implemented yet 94 err = fmt.Errorf("encryption method %s not implemented yet", method) 95 default: 96 log.Fatalf("Enc method %s not known", method) 97 os.Exit(1) 98 } 99 100 if err != nil { 101 log.Debug("encryption data failed") 102 return 103 } 104 log.Debug("encryption data success") 105 return 106 } 107 108 // ListPasswords printout list of pwcli 109 func (pc *PassConfig) ListPasswords() (lines []string, err error) { 110 log.Debugf("ListPasswords entered") 111 lines, err = pc.DecryptFile() 112 if err != nil { 113 log.Errorf("Decode Failed") 114 return 115 } 116 return 117 } 118 119 // GetPassword ask System for data 120 func (pc *PassConfig) GetPassword(system string, account string) (password string, err error) { 121 var lines []string 122 log.Debugf("GetPassword for '%s'@'%s' entered", account, system) 123 if pc.Method == typeVault { 124 // in vault mode we use cryptedfile to handover vault path 125 pc.CryptedFile = system 126 } 127 lines, err = pc.DecryptFile() 128 if err != nil { 129 return 130 } 131 found := false 132 direct := false 133 if pc.Method == typeVault { 134 // in vault mode we need to replace ":" in system = vault path to match 135 system = strings.ReplaceAll(system, ":", "_") 136 } 137 138 // match strings in function to make linter happy 139 password, found, direct = pc.match(lines, system, account) 140 // not found 141 if !found { 142 msg := fmt.Sprintf("no record found for '%s'@'%s'", account, system) 143 log.Debug("GetPassword finished with no Match") 144 err = errors.New(msg) 145 return 146 } 147 148 // found 149 if !direct { 150 log.Debug("use default entry") 151 } 152 return 153 } 154 155 func (pc *PassConfig) match(lines []string, system string, account string) (password string, found bool, direct bool) { 156 password = "" 157 found = false 158 direct = false 159 for _, line := range lines { 160 if common.CheckSkip(line) { 161 continue 162 } 163 fields := strings.SplitN(line, ":", 3) 164 if len(fields) != 3 { 165 log.Debugf("Skip incomplete record %s", line) 166 continue 167 } 168 if system == fields[0] && account == fields[1] { 169 log.Debug("Found direct match") 170 if found { 171 log.Debug("Overwrite previous default candidate") 172 } 173 found = true 174 direct = true 175 password = fields[2] 176 break 177 } 178 if pc.Method == typeVault || pc.Method == typeGopass { 179 // vault method has no default entries 180 continue 181 } 182 if fields[0] == "!default" && account == fields[1] { 183 password = fields[2] 184 log.Debug("found new default match candidate") 185 if found { 186 log.Debug("Overwrite previous default candidate") 187 } 188 found = true 189 } 190 } 191 return 192 }