mirror of
https://github.com/drakkan/sftpgo.git
synced 2025-12-08 23:28:39 +03:00
add check password hook
its main use case is to allow to easily support things like password+OTP for protocols without keyboard interactive support such as FTP and WebDAV
This commit is contained in:
@@ -129,6 +129,7 @@ var (
|
||||
keyIntAuthPath string
|
||||
preLoginPath string
|
||||
postConnectPath string
|
||||
checkPwdPath string
|
||||
logFilePath string
|
||||
)
|
||||
|
||||
@@ -203,6 +204,7 @@ func TestMain(m *testing.M) {
|
||||
extAuthPath = filepath.Join(homeBasePath, "extauth.sh")
|
||||
preLoginPath = filepath.Join(homeBasePath, "prelogin.sh")
|
||||
postConnectPath = filepath.Join(homeBasePath, "postconnect.sh")
|
||||
checkPwdPath = filepath.Join(homeBasePath, "checkpwd.sh")
|
||||
err = ioutil.WriteFile(pubKeyPath, []byte(testPubKey+"\n"), 0600)
|
||||
if err != nil {
|
||||
logger.WarnToConsole("unable to save public key to file: %v", err)
|
||||
@@ -277,6 +279,7 @@ func TestMain(m *testing.M) {
|
||||
os.Remove(preLoginPath)
|
||||
os.Remove(postConnectPath)
|
||||
os.Remove(keyIntAuthPath)
|
||||
os.Remove(checkPwdPath)
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
|
||||
@@ -1487,6 +1490,77 @@ func TestPostConnectHook(t *testing.T) {
|
||||
common.Config.PostConnectHook = ""
|
||||
}
|
||||
|
||||
func TestCheckPwdHook(t *testing.T) {
|
||||
if runtime.GOOS == osWindows {
|
||||
t.Skip("this test is not available on Windows")
|
||||
}
|
||||
usePubKey := false
|
||||
u := getTestUser(usePubKey)
|
||||
u.QuotaFiles = 1000
|
||||
err := dataprovider.Close()
|
||||
assert.NoError(t, err)
|
||||
err = config.LoadConfig(configDir, "")
|
||||
assert.NoError(t, err)
|
||||
providerConf := config.GetProviderConf()
|
||||
err = ioutil.WriteFile(checkPwdPath, getCheckPwdScriptsContents(2, defaultPassword), os.ModePerm)
|
||||
assert.NoError(t, err)
|
||||
providerConf.CheckPasswordHook = checkPwdPath
|
||||
providerConf.CheckPasswordScope = 1
|
||||
err = dataprovider.Initialize(providerConf, configDir)
|
||||
assert.NoError(t, err)
|
||||
user, _, err := httpd.AddUser(u, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
|
||||
client, err := getSftpClient(user, usePubKey)
|
||||
if assert.NoError(t, err) {
|
||||
err = checkBasicSFTP(client)
|
||||
assert.NoError(t, err)
|
||||
client.Close()
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(checkPwdPath, getCheckPwdScriptsContents(0, defaultPassword), os.ModePerm)
|
||||
assert.NoError(t, err)
|
||||
client, err = getSftpClient(user, usePubKey)
|
||||
if !assert.Error(t, err) {
|
||||
client.Close()
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(checkPwdPath, getCheckPwdScriptsContents(1, ""), os.ModePerm)
|
||||
assert.NoError(t, err)
|
||||
user.Password = defaultPassword + "1"
|
||||
client, err = getSftpClient(user, usePubKey)
|
||||
if assert.NoError(t, err) {
|
||||
err = checkBasicSFTP(client)
|
||||
assert.NoError(t, err)
|
||||
client.Close()
|
||||
}
|
||||
|
||||
err = dataprovider.Close()
|
||||
assert.NoError(t, err)
|
||||
providerConf.CheckPasswordScope = 6
|
||||
err = dataprovider.Initialize(providerConf, configDir)
|
||||
assert.NoError(t, err)
|
||||
client, err = getSftpClient(user, usePubKey)
|
||||
if !assert.Error(t, err) {
|
||||
client.Close()
|
||||
}
|
||||
|
||||
_, err = httpd.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = dataprovider.Close()
|
||||
assert.NoError(t, err)
|
||||
err = config.LoadConfig(configDir, "")
|
||||
assert.NoError(t, err)
|
||||
providerConf = config.GetProviderConf()
|
||||
err = dataprovider.Initialize(providerConf, configDir)
|
||||
assert.NoError(t, err)
|
||||
err = os.Remove(checkPwdPath)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestLoginExternalAuthPwdAndPubKey(t *testing.T) {
|
||||
if runtime.GOOS == osWindows {
|
||||
t.Skip("this test is not available on Windows")
|
||||
@@ -7557,6 +7631,17 @@ func getPostConnectScriptContent(exitCode int) []byte {
|
||||
return content
|
||||
}
|
||||
|
||||
func getCheckPwdScriptsContents(status int, toVerify string) []byte {
|
||||
content := []byte("#!/bin/sh\n\n")
|
||||
content = append(content, []byte(fmt.Sprintf("echo '{\"status\":%v,\"to_verify\":\"%v\"}'\n", status, toVerify))...)
|
||||
if status > 0 {
|
||||
content = append(content, []byte("exit 0")...)
|
||||
} else {
|
||||
content = append(content, []byte("exit 1")...)
|
||||
}
|
||||
return content
|
||||
}
|
||||
|
||||
func printLatestLogs(maxNumberOfLines int) {
|
||||
var lines []string
|
||||
f, err := os.Open(logFilePath)
|
||||
|
||||
Reference in New Issue
Block a user