From 14a446df716ea8a237a3f632d4d97f5e87e6f5a5 Mon Sep 17 00:00:00 2001 From: Chris Mann Date: Sun, 23 Jul 2023 08:22:09 +0200 Subject: [PATCH] Adding LDAPS with newuser permissions OK --- go.mod | 4 +- go.sum | 4 ++ gpas.go | 67 +++++++++++++++++++++++++++++++ invite.go | 50 +++++++++++++++++++---- login.go | 7 +--- main.go | 1 + templates/invite_new_account.html | 4 +- templates/lost_password.html | 28 +++++++++++++ 8 files changed, 149 insertions(+), 16 deletions(-) create mode 100644 gpas.go create mode 100644 templates/lost_password.html diff --git a/go.mod b/go.mod index bacf791..110a691 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,8 @@ go 1.18 require ( git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang v0.0.0-20230131081355-c965fe7f7dc9 - github.com/emersion/go-sasl v0.0.0-20191210011802-430746ea8b9b - github.com/emersion/go-smtp v0.12.1 + github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 + github.com/emersion/go-smtp v0.17.0 github.com/go-ldap/ldap/v3 v3.1.6 github.com/google/uuid v1.1.1 github.com/gorilla/mux v1.7.3 diff --git a/go.sum b/go.sum index 3e2e72d..ba088b9 100644 --- a/go.sum +++ b/go.sum @@ -48,8 +48,12 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn github.com/emersion/go-sasl v0.0.0-20190817083125-240c8404624e/go.mod h1:G/dpzLu16WtQpBfQ/z3LYiYJn3ZhKSGWn83fyoyQe/k= github.com/emersion/go-sasl v0.0.0-20191210011802-430746ea8b9b h1:uhWtEWBHgop1rqEk2klKaxPAkVDCXexai6hSuRQ7Nvs= github.com/emersion/go-sasl v0.0.0-20191210011802-430746ea8b9b/go.mod h1:G/dpzLu16WtQpBfQ/z3LYiYJn3ZhKSGWn83fyoyQe/k= +github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 h1:OJyUGMJTzHTd1XQp98QTaHernxMYzRaOasRir9hUlFQ= +github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ= github.com/emersion/go-smtp v0.12.1 h1:1R8BDqrR2HhlGwgFYcOi+BVTvK1bMjAB65QcVpJ5sNA= github.com/emersion/go-smtp v0.12.1/go.mod h1:SD9V/xa4ndMw77lR3Mf7htkp8RBNYuPh9UeuBs9tpUQ= +github.com/emersion/go-smtp v0.17.0 h1:tq90evlrcyqRfE6DSXaWVH54oX6OuZOQECEmhWBMEtI= +github.com/emersion/go-smtp v0.17.0/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= diff --git a/gpas.go b/gpas.go new file mode 100644 index 0000000..d4c0113 --- /dev/null +++ b/gpas.go @@ -0,0 +1,67 @@ +/* +gpas is GVoisin password reset +*/ + +package main + +import ( + "bytes" + "errors" + "fmt" + "html/template" + "log" + + "github.com/emersion/go-sasl" + "github.com/emersion/go-smtp" + "github.com/go-ldap/ldap/v3" + // "strings" +) + +// var EMAIL_REGEXP := regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$") + +func passwordLost(user User, config *ConfigFile, ldapConn *ldap.Conn) error { + if user.CN == "" && user.Mail == "" && user.OtherMailbox == "" { + return errors.New("Il n'y a pas de quoi identifier l'utilisateur") + } + searchFilter := "(|" + if user.CN == "" { + searchFilter += "(cn=" + user.CN + ")" + } + if user.Mail == "" { + searchFilter += "(mail=" + user.Mail + ")" + } + if user.OtherMailbox == "" { + searchFilter += "(carLicense=" + user.OtherMailbox + ")" + } + searchReq := ldap.NewSearchRequest(config.UserBaseDN, ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false, "(|()()())", []string{"cn", "uid", "mail", "carLicense"}, nil) + searchRes, err := ldapConn.Search(searchReq) + err = l.Bind(config.NewUserDN, config.NewUserPassword) + if err != nil { + log.Printf(fmt.Sprintf("passwordLost : %v %v", err, l)) + } + if len(searchRes.Entries) == 0 { + return errors.New("Il n'y a pas d'utilisateur qui correspond") + } + // Préparation du courriel à envoyer + code := "GPas" + templateMail := template.Must(template.ParseFiles(templatePath + "/invite_mail.txt")) + buf := bytes.NewBuffer([]byte{}) + templateMail.Execute(buf, &CodeMailFields{ + To: user.OtherMailbox, + From: config.MailFrom, + InviteFrom: "GPas", + Code: code, + WebBaseAddress: config.WebAddress, + }) + log.Printf("Sending mail to: %s", user.OtherMailbox) + var auth sasl.Client = nil + if config.SMTPUsername != "" { + auth = sasl.NewPlainClient("", config.SMTPUsername, config.SMTPPassword) + } + err = smtp.SendMail(config.SMTPServer, auth, config.MailFrom, []string{user.OtherMailbox}, buf) + if err != nil { + return err + } + log.Printf("Mail sent.") + return nil +} diff --git a/invite.go b/invite.go index 0ad99dd..4da8d31 100644 --- a/invite.go +++ b/invite.go @@ -38,6 +38,42 @@ func checkInviterLogin(w http.ResponseWriter, r *http.Request) *LoginStatus { // New account creation directly from interface +type LostPasswordData struct { + Username string + Mail string + OtherMailbox string +} + +func handleLostPassword(w http.ResponseWriter, r *http.Request) { + templateLostPasswordPage := getTemplate("lost_password.html") + l, err := ldapOpen(w) + if err != nil { + log.Printf(fmt.Sprintf("handleLostPassword : %v %v", err, l)) + } + err = l.Bind(config.NewUserDN, config.NewUserPassword) + if err != nil { + log.Printf(fmt.Sprintf("handleLostPassword : %v %v", err, l)) + } + data := LostPasswordData{} + if r.Method == "POST" { + r.ParseForm() + data.Username = strings.TrimSpace(strings.Join(r.Form["username"], "")) + data.Mail = strings.TrimSpace(strings.Join(r.Form["mail"], "")) + data.OtherMailbox = strings.TrimSpace(strings.Join(r.Form["otherMailbox"], "")) + user := User{ + CN: data.Username, + Mail: data.Mail, + OtherMailbox: data.OtherMailbox, + } + err = passwordLost(user, config, l) + err = l.Bind(config.NewUserDN, config.NewUserPassword) + if err != nil { + log.Printf(fmt.Sprintf("handleLostPassword : %v %v", err, l)) + } + } + templateLostPasswordPage.Execute(w, data) +} + func handleInviteNewAccount(w http.ResponseWriter, r *http.Request) { l, err := ldapOpen(w) if err != nil { @@ -54,9 +90,9 @@ func handleInviteNewAccount(w http.ResponseWriter, r *http.Request) { // loginInfo, err := doLogin(w, r, "testuser", config.NewUserDN, config.NewUserPassword) - if err != nil { - log.Printf(fmt.Sprintf("58: %v %v", err, l)) - } + // if err != nil { + // log.Printf(fmt.Sprintf("58: %v %v", err, l)) + // } // l := ldapOpen(w) if l == nil { @@ -129,7 +165,7 @@ type NewAccountData struct { Surname string Mail string SuggestPW string - CN string + OtherEmail string ErrorUsernameTaken bool ErrorInvalidUsername bool @@ -156,9 +192,9 @@ func handleNewAccount(w http.ResponseWriter, r *http.Request, l *ldap.Conn, invi newUser.GivenName = strings.TrimSpace(strings.Join(r.Form["givenname"], "")) newUser.SN = strings.TrimSpace(strings.Join(r.Form["surname"], "")) newUser.Mail = strings.TrimSpace(strings.Join(r.Form["mail"], "")) - newUser.UID = strings.TrimSpace(strings.Join(r.Form["username"], "")) - newUser.CN = strings.TrimSpace(strings.Join(r.Form["cn"], "")) - newUser.DN = "cn=" + strings.TrimSpace(strings.Join(r.Form["cn"], "")) + "," + config.InvitationBaseDN + newUser.UID = strings.TrimSpace(strings.Join(r.Form["otheremail"], "")) + newUser.CN = strings.TrimSpace(strings.Join(r.Form["username"], "")) + newUser.DN = "cn=" + strings.TrimSpace(strings.Join(r.Form["username"], "")) + "," + config.InvitationBaseDN password1 := strings.Join(r.Form["password"], "") password2 := strings.Join(r.Form["password2"], "") diff --git a/login.go b/login.go index 51b23fe..78de374 100644 --- a/login.go +++ b/login.go @@ -73,8 +73,6 @@ func checkLogin(w http.ResponseWriter, r *http.Request) *LoginStatus { Password: login_info.Password, }, config, l) - // err = l.Bind(login_info.DN, login_info.Password) - if err != nil { delete(session.Values, "login_username") delete(session.Values, "login_password") @@ -108,8 +106,6 @@ func checkLogin(w http.ResponseWriter, r *http.Request) *LoginStatus { CanInvite: ldapUser.CanInvite, } - return loginStatus - /* requestKind := "(objectClass=organizationalPerson)" @@ -196,6 +192,8 @@ func checkLogin(w http.ResponseWriter, r *http.Request) *LoginStatus { return loginStatus */ + + return loginStatus } func handleLogout(w http.ResponseWriter, r *http.Request) { @@ -304,5 +302,4 @@ func doLogin(w http.ResponseWriter, r *http.Request, username string, user_dn st } return &LoginInfo, nil - } diff --git a/main.go b/main.go index d2d8355..8db01d4 100644 --- a/main.go +++ b/main.go @@ -75,6 +75,7 @@ func main() { r.HandleFunc("/invite/new_account", handleInviteNewAccount) r.HandleFunc("/invite/send_code", handleInviteSendCode) + r.HandleFunc("/gpas", handleLostPassword) r.HandleFunc("/invitation/{code}", handleInvitationCode) r.HandleFunc("/admin/users", handleAdminUsers) diff --git a/templates/invite_new_account.html b/templates/invite_new_account.html index 0e89a41..deec2c1 100644 --- a/templates/invite_new_account.html +++ b/templates/invite_new_account.html @@ -31,8 +31,8 @@
- - + + Le courriel de l'utilisateur. diff --git a/templates/lost_password.html b/templates/lost_password.html new file mode 100644 index 0000000..e034a15 --- /dev/null +++ b/templates/lost_password.html @@ -0,0 +1,28 @@ +

G Pas

+ +

Refaire son mot de passe

+ +{{if .ErrorMessage}} +
Impossible +
{{ .ErrorMessage }}
+
+{{end}} +{{if .Success}} +
+ Email envoyé au courriel de secours. +
+{{end}} + +
+
+ + +
+
+ + +
+
+ + +
\ No newline at end of file