Golang : Verify Linux user password again before executing a program example
One of my previous tutorial shows you how to restrict a program execution to root
only and this can be restrictive for some as the root password needs to be shared around. Mr. Jake of the Philipines would like to know how to force a user to enter his or her username and password before allowing a program to execute. Instead of hard coding the password/username into the code, he needs know how his program can authenticate the username and password against the Linux's user/password database.
In Linux, we can use the PAM(Pluggable Authentication Module) to check if a username/password is valid before allowing further execution of the program.
The code example below uses the Linux PAM(Pluggable Authentication Module) to verify if a username and password are registered in the Linux's database. If yes, allow the user to proceed and if not, simply abort the program.
NOTE: In case the code did not compile due to a missing library. Install libpam0g-dev
on your Linux machine. sudo yum install libpam0g-dev
or sudo apt-get install libpam0g-dev
should fix the issue.
NOTE: Do not use this program on none Linux OS.
Here you go!
package main
import (
"bufio"
"errors"
"fmt"
"github.com/bgentry/speakeasy"
"github.com/msteinert/pam"
"os"
"runtime"
)
func authService() error {
t, err := pam.StartFunc("", "", func(s pam.Style, msg string) (string, error) {
switch s {
case pam.PromptEchoOff:
return speakeasy.Ask(msg)
case pam.PromptEchoOn:
fmt.Print(msg + " ")
input, err := bufio.NewReader(os.Stdin).ReadString('\n')
if err != nil {
return "", err
}
return input[:len(input)-1], nil
case pam.ErrorMsg:
fmt.Print(msg)
return "", nil
case pam.TextInfo:
fmt.Println(msg)
return "", nil
}
return "", errors.New("Unrecognized message style")
})
if err != nil {
return err
}
err = t.Authenticate(0)
if err != nil {
return err
}
//fmt.Println("Authentication succeeded!")
return nil
}
func main() {
if runtime.GOOS != "linux" { // also can be specified to FreeBSD
fmt.Println("PAM(Pluggable Authentication Modules) only works with Linux!!")
os.Exit(0)
}
err := authService()
if err != nil {
fmt.Println("Unable to authenticate your password or username! Abort!")
} else {
fmt.Println("Credential accepted! Proceeding to .....")
// this is where you want to execute your main function for authenticated users.
}
}
Execute the code and feed it with valid and none valid username/password combinations to see the differences.
Happy coding!
References:
https://godoc.org/github.com/msteinert/pam#example-package--Authenticate
See also : Golang : Get login name from environment and prompt for password
By Adam Ng
IF you gain some knowledge or the information here solved your programming problem. Please consider donating to the less fortunate or some charities that you like. Apart from donation, planting trees, volunteering or reducing your carbon footprint will be great too.
Advertisement
Tutorials
+3.7k Chrome : How to block socketloop.com links in Google SERP?
+8.9k Golang : Channels and buffered channels examples
+10.7k Golang : Clean formatting/indenting or pretty print JSON result
+18.1k Golang : How to run your code only once with sync.Once object
+29.5k Golang : bufio.NewReader.ReadLine to read file line by line
+11.7k Python : Convert IPv6 address to decimal and back to IPv6
+18.5k Golang : Append content to a file
+7.2k Your page has meta tags in the body instead of the head
+10.4k SSL : The certificate is not trusted because no issuer chain was provided
+13.2k Golang : Overwrite previous output with count down timer
+3.7k Linux : sudo yum updates not working
+8.4k Golang : How to protect your source code from client, hosting company or hacker?