Password change
This commit is contained in:
parent
6297981c3b
commit
27a411fe69
1
go.mod
1
go.mod
@ -6,4 +6,5 @@ require (
|
|||||||
github.com/go-ldap/ldap v3.0.3+incompatible
|
github.com/go-ldap/ldap v3.0.3+incompatible
|
||||||
github.com/go-ldap/ldap/v3 v3.1.6
|
github.com/go-ldap/ldap/v3 v3.1.6
|
||||||
github.com/gorilla/sessions v1.2.0
|
github.com/gorilla/sessions v1.2.0
|
||||||
|
github.com/sirupsen/logrus v1.4.2
|
||||||
)
|
)
|
||||||
|
10
go.sum
10
go.sum
@ -1,3 +1,4 @@
|
|||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/go-asn1-ber/asn1-ber v1.3.1 h1:gvPdv/Hr++TRFCl0UbPFHC54P9N9jgsRPnmnr419Uck=
|
github.com/go-asn1-ber/asn1-ber v1.3.1 h1:gvPdv/Hr++TRFCl0UbPFHC54P9N9jgsRPnmnr419Uck=
|
||||||
github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||||
github.com/go-ldap/ldap v3.0.3+incompatible h1:HTeSZO8hWMS1Rgb2Ziku6b8a7qRIZZMHjsvuZyatzwk=
|
github.com/go-ldap/ldap v3.0.3+incompatible h1:HTeSZO8hWMS1Rgb2Ziku6b8a7qRIZZMHjsvuZyatzwk=
|
||||||
@ -8,3 +9,12 @@ github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyC
|
|||||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||||
github.com/gorilla/sessions v1.2.0 h1:S7P+1Hm5V/AT9cjEcUD5uDaQSX0OE577aCXgoaKpYbQ=
|
github.com/gorilla/sessions v1.2.0 h1:S7P+1Hm5V/AT9cjEcUD5uDaQSX0OE577aCXgoaKpYbQ=
|
||||||
github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||||
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
|
||||||
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
45
main.go
45
main.go
@ -94,6 +94,7 @@ func main() {
|
|||||||
http.HandleFunc("/", handleHome)
|
http.HandleFunc("/", handleHome)
|
||||||
http.HandleFunc("/logout", handleLogout)
|
http.HandleFunc("/logout", handleLogout)
|
||||||
http.HandleFunc("/profile", handleProfile)
|
http.HandleFunc("/profile", handleProfile)
|
||||||
|
http.HandleFunc("/passwd", handlePasswd)
|
||||||
|
|
||||||
staticfiles := http.FileServer(http.Dir("static"))
|
staticfiles := http.FileServer(http.Dir("static"))
|
||||||
http.Handle("/static/", http.StripPrefix("/static/", staticfiles))
|
http.Handle("/static/", http.StripPrefix("/static/", staticfiles))
|
||||||
@ -358,3 +359,47 @@ func handleProfile(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
templateProfile.Execute(w, data)
|
templateProfile.Execute(w, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PasswdTplData struct {
|
||||||
|
Status *LoginStatus
|
||||||
|
ErrorMessage string
|
||||||
|
NoMatchError bool
|
||||||
|
Success bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func handlePasswd(w http.ResponseWriter, r *http.Request) {
|
||||||
|
templatePasswd := template.Must(template.ParseFiles("templates/layout.html", "templates/passwd.html"))
|
||||||
|
|
||||||
|
login := checkLogin(w, r)
|
||||||
|
if login == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data := &PasswdTplData{
|
||||||
|
Status: login,
|
||||||
|
ErrorMessage: "",
|
||||||
|
Success: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.Method == "POST" {
|
||||||
|
r.ParseForm()
|
||||||
|
|
||||||
|
password := strings.Join(r.Form["password"], "")
|
||||||
|
password2 := strings.Join(r.Form["password2"], "")
|
||||||
|
|
||||||
|
if password2 != password {
|
||||||
|
data.NoMatchError = true
|
||||||
|
} else {
|
||||||
|
modify_request := ldap.NewModifyRequest(login.Info.DN, nil)
|
||||||
|
modify_request.Replace("userpassword", []string{SSHAEncode([]byte(password))})
|
||||||
|
err := login.conn.Modify(modify_request)
|
||||||
|
if err != nil {
|
||||||
|
data.ErrorMessage = err.Error()
|
||||||
|
} else {
|
||||||
|
data.Success = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
templatePasswd.Execute(w, data)
|
||||||
|
}
|
||||||
|
37
ssha.go
Normal file
37
ssha.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/sha1"
|
||||||
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Encode encodes the []byte of raw password
|
||||||
|
func SSHAEncode(rawPassPhrase []byte) string {
|
||||||
|
hash := makeSSHAHash(rawPassPhrase, makeSalt())
|
||||||
|
b64 := base64.StdEncoding.EncodeToString(hash)
|
||||||
|
return fmt.Sprintf("{ssha}%s", b64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// makeSalt make a 32 byte array containing random bytes.
|
||||||
|
func makeSalt() []byte {
|
||||||
|
sbytes := make([]byte, 32)
|
||||||
|
_, err := rand.Read(sbytes)
|
||||||
|
if err != nil {
|
||||||
|
log.Panicf("Could not read random bytes: %s", err)
|
||||||
|
}
|
||||||
|
return sbytes
|
||||||
|
}
|
||||||
|
|
||||||
|
// makeSSHAHash make hasing using SHA-1 with salt. This is not the final output though. You need to append {SSHA} string with base64 of this hash.
|
||||||
|
func makeSSHAHash(passphrase, salt []byte) []byte {
|
||||||
|
sha := sha1.New()
|
||||||
|
sha.Write(passphrase)
|
||||||
|
sha.Write(salt)
|
||||||
|
|
||||||
|
h := sha.Sum(nil)
|
||||||
|
return append(h, salt...)
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
{{define "title"}}{{end}}
|
{{define "title"}}{{end}}
|
||||||
|
|
||||||
{{define "body"}}
|
{{define "body"}}
|
||||||
|
<h4>S'identifier</h4>
|
||||||
|
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
{{if .ErrorMessage}}
|
{{if .ErrorMessage}}
|
||||||
|
37
templates/passwd.html
Normal file
37
templates/passwd.html
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
{{define "title"}}Mot de passe |{{end}}
|
||||||
|
|
||||||
|
{{define "body"}}
|
||||||
|
<h4>Modifier mon mot de passe</h4>
|
||||||
|
|
||||||
|
{{if .ErrorMessage}}
|
||||||
|
<div class="alert alert-danger">Impossible d'effectuer la modification.
|
||||||
|
<div style="font-size: 0.8em">{{ .ErrorMessage }}</div>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
{{if .Success}}
|
||||||
|
<div class="alert alert-success">
|
||||||
|
Nouveau mot de passe enregistré.
|
||||||
|
</div>
|
||||||
|
<a class="ml-auto btn btn-info" href="/">Retour</a>
|
||||||
|
{{else}}
|
||||||
|
<form method="POST">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="password">Nouveau mot de passe :</label>
|
||||||
|
<input type="password" id="password" name="password" class="form-control" />
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="password2">Répéter le mot de passe :</label>
|
||||||
|
<input type="password" id="password2" name="password2" class="form-control" />
|
||||||
|
</div>
|
||||||
|
{{if .NoMatchError}}
|
||||||
|
<div class="alert alert-warning">
|
||||||
|
Les deux mots de passe entrés ne correspondent pas.
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
<div class="d-flex">
|
||||||
|
<button type="submit" class="btn btn-primary">Changer de mot de passe</button>
|
||||||
|
<a class="ml-auto btn btn-danger" href="/">Annuler</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
@ -3,20 +3,18 @@
|
|||||||
{{define "body"}}
|
{{define "body"}}
|
||||||
<h4>Modifier mon profil</h4>
|
<h4>Modifier mon profil</h4>
|
||||||
|
|
||||||
<form method="POST">
|
|
||||||
{{if .ErrorMessage}}
|
{{if .ErrorMessage}}
|
||||||
<div class="alert alert-danger">Impossible de se connecter.
|
<div class="alert alert-danger">Impossible d'effectuer la modification.
|
||||||
<div style="font-size: 0.8em">{{ .ErrorMessage }}</div>
|
<div style="font-size: 0.8em">{{ .ErrorMessage }}</div>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if .Success}}
|
{{if .Success}}
|
||||||
<div class="alert alert-success">
|
<div class="alert alert-success">
|
||||||
<div class="d-flex">
|
Profil enregistré.
|
||||||
<span>Profil enregistré.</span>
|
|
||||||
<a class="ml-auto btn btn-sm btn-info" href="/">Retour</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<a class="ml-auto btn btn-info" href="/">Retour</a>
|
||||||
{{end}}
|
{{else}}
|
||||||
|
<form method="POST">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>Nom d'utilisateur:</label>
|
<label>Nom d'utilisateur:</label>
|
||||||
<input type="text" disabled="true" class="form-control" value="{{ .Status.Info.Username }}" />
|
<input type="text" disabled="true" class="form-control" value="{{ .Status.Info.Username }}" />
|
||||||
@ -43,3 +41,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
Loading…
Reference in New Issue
Block a user