Can launch the executable with arguments to get reset token
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
nemunaire 2025-01-06 14:46:11 +01:00
parent 3ec3d2649f
commit c671d26205
2 changed files with 57 additions and 18 deletions

44
lost.go
View File

@ -51,6 +51,25 @@ func (l LDAPConn) genToken(dn string, previous bool) string {
return base64.StdEncoding.EncodeToString(hash.Sum(nil)[:])
}
func lostPasswordToken(conn *LDAPConn, login string) (string, string, error) {
// Bind as service to perform the search
err := conn.ServiceBind()
if err != nil {
return "", "", err
}
// Search the dn of the given user
dn, err := conn.SearchDN(login, true)
if err != nil {
return "", "", err
}
// Generate the token
token := conn.genToken(dn, false)
return token, dn, nil
}
func lostPassword(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
displayTmpl(w, "lost.html", map[string]interface{}{})
@ -65,24 +84,13 @@ func lostPassword(w http.ResponseWriter, r *http.Request) {
return
}
// Bind as service to perform the search
err = conn.ServiceBind()
if err != nil {
log.Println(err)
displayTmplError(w, http.StatusInternalServerError, "lost.html", map[string]interface{}{"error": err.Error()})
return
}
// Search the dn of the given user
dn, err := conn.SearchDN(r.PostFormValue("login"), true)
if err != nil {
log.Println(err)
displayTmplError(w, http.StatusInternalServerError, "lost.html", map[string]interface{}{"error": err.Error()})
return
}
// Generate the token
token := conn.genToken(dn, false)
token, dn, err := lostPasswordToken(conn, r.PostFormValue("login"))
if err != nil {
log.Println(err)
displayTmplError(w, http.StatusInternalServerError, "lost.html", map[string]interface{}{"error": err.Error()})
return
}
// Search the email address
entries, err := conn.GetEntry(dn)
@ -114,7 +122,7 @@ func lostPassword(w http.ResponseWriter, r *http.Request) {
m.SetHeader("From", "noreply@nemunai.re")
m.SetHeader("To", email)
m.SetHeader("Subject", "SSO nemunai.re: password recovery")
m.SetBody("text/plain", "Hello "+cn+"!\n\nSomeone, and we hope it's you, requested to reset your account password. \nIn order to continue, go to:\nhttps://ldap.nemunai.re/reset?l="+r.PostFormValue("login")+"&t="+token+"\n\nBest regards,\n-- \nnemunai.re SSO")
m.SetBody("text/plain", "Hello "+cn+"!\n\nSomeone, and we hope it's you, requested to reset your account password. \nIn order to continue, go to:\n"+BASEURL+"/reset?l="+r.PostFormValue("login")+"&t="+token+"\n\nBest regards,\n-- \nnemunai.re SSO")
var s gomail.Sender
if myLDAP.MailHost != "" {

31
main.go
View File

@ -17,6 +17,8 @@ import (
"syscall"
)
const BASEURL = "https://ldap.nemunai.re"
var myLDAP = LDAP{
Host: "localhost",
Port: 389,
@ -143,6 +145,35 @@ func main() {
myLDAP.MailPassword = val
}
if flag.NArg() > 0 {
switch flag.Arg(0) {
case "generate-lost-password-link":
if flag.NArg() != 2 {
log.Fatal("Need a second argument: email of the user to reset")
}
login := flag.Arg(1)
conn, err := myLDAP.Connect()
if err != nil || conn == nil {
log.Fatalf("Unable to connect to LDAP: %s", err.Error())
}
token, dn, err := lostPasswordToken(conn, login)
if err != nil {
log.Fatal(err.Error())
}
fmt.Printf("Reset link for %s: %s/reset?l=%s&t=%s", dn, BASEURL, login, token)
return
case "serve":
case "server":
break
default:
log.Fatalf("%q is not a valid command", flag.Arg(0))
}
}
// Prepare graceful shutdown
interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM)