package main import ( "crypto/rand" "crypto/sha512" "encoding/base64" "fmt" "log" randm "math/rand" "os" "strings" "github.com/go-ldap/ldap/v3" "github.com/go-yaml/yaml" ) type conf struct { LdapUrl string `yaml:"ldapurl"` BaseDN string `yaml:"basedn"` BindDN string `yaml:"binddn"` BindPW string `yaml:"bindpw"` } func (c *conf) get_config() *conf { f, err := os.ReadFile("config.yaml") if err != nil { log.Fatal(err) } err = yaml.Unmarshal(f, c) if err != nil { log.Fatal(err) } return c } // Gettings uids of people that needs a password change func get_uids(ldap_conn *ldap.Conn, basedn string) []string { uids := []string{} search_req := ldap.NewSearchRequest(basedn, ldap.ScopeWholeSubtree, 0, 0, 0, false, "(uid=*)", []string{"uid", "userPassword"}, nil) res, err := ldap_conn.Search(search_req) if err != nil { log.Fatal(err) } for _, entry := range res.Entries { uid := entry.GetAttributeValue("uid") password := entry.GetAttributeValue("userPassword") if strings.HasPrefix(password, "{SSHA}") { uids = append(uids, uid) } } return uids } func get_random_password(length int) string { characters := []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") var sb strings.Builder for i := 0; i < length; i++ { sb.WriteRune(characters[randm.Intn(len(characters))]) } return sb.String() } func get_salt() ([]byte, error) { salt := make([]byte, 4) _, err := rand.Read(salt) if err != nil { return nil, err } return salt, nil } func get_hash(password string, salt []byte) []byte { password_bytes := []byte(password) password_salt := append(password_bytes, salt...) sum := sha512.Sum512(password_salt) res := append(sum[:], salt...) return res } func change_password(ldap_conn *ldap.Conn, basedn string, uid string) { password := get_random_password(20) salt, err := get_salt() if err != nil { log.Fatal(err) } new_pass := "{SSHA512}" + base64.StdEncoding.EncodeToString(get_hash(password, salt)) modify_req := ldap.NewModifyRequest("uid="+uid+","+basedn, nil) modify_req.Replace("userPassword", []string{new_pass}) err = ldap_conn.Modify(modify_req) if err != nil { log.Fatal(err) } fmt.Printf("%s : %s \n", uid, password) } func main() { var c conf c.get_config() l, err := ldap.DialURL(c.LdapUrl) if err != nil { log.Fatal(err) } defer l.Close() err = l.Bind(c.BindDN, c.BindPW) if err != nil { log.Fatal(err) } uids := get_uids(l, c.BaseDN) for _, uid := range uids { change_password(l, c.BaseDN, uid) } }