+func (c *Client) Register(cmd string, cols []string) {
+ switch cmd {
+ case "PASS":
+ if len(cols) == 1 || len(cols[1]) < 1 {
+ c.ReplyNotEnoughParameters("PASS")
+ return
+ }
+ password := strings.TrimPrefix(cols[1], ":")
+ c.password = password
+ case "NICK":
+ if len(cols) == 1 || len(cols[1]) < 1 {
+ c.ReplyParts("431", "No nickname given")
+ return
+ }
+ nickname := cols[1]
+ // Compatibility with some clients prepending colons to nickname
+ nickname = strings.TrimPrefix(nickname, ":")
+ nickname = strings.ToLower(nickname)
+ if !RENickname.MatchString(nickname) {
+ c.ReplyParts("432", "*", cols[1], "Erroneous nickname")
+ return
+ }
+ clientsLock.RLock()
+ for existingClient := range clients {
+ if existingClient.nickname == nickname {
+ clientsLock.RUnlock()
+ c.ReplyParts("433", "*", nickname, "Nickname is already in use")
+ return
+ }
+ }
+ clientsLock.RUnlock()
+ c.nickname = nickname
+ case "USER":
+ if len(cols) == 1 {
+ c.ReplyNotEnoughParameters("USER")
+ return
+ }
+ args := strings.SplitN(cols[1], " ", 4)
+ if len(args) < 4 {
+ c.ReplyNotEnoughParameters("USER")
+ return
+ }
+ c.username = args[0]
+ realname := strings.TrimLeft(args[3], ":")
+ c.realname = realname
+ }
+ if c.nickname != "*" && c.username != "" {
+ if *passwords != "" {
+ authenticated := false
+ if c.password == "" {
+ c.ReplyParts("462", "You may not register")
+ c.Close()
+ return
+ }
+ contents, err := os.ReadFile(*passwords)
+ if err != nil {
+ log.Fatalf("can not read passwords file %s: %s", *passwords, err)
+ return
+ }
+ for n, entry := range strings.Split(string(contents), "\n") {
+ if entry == "" || strings.HasPrefix(entry, "#") {
+ continue
+ }
+ cols := strings.Split(entry, ":")
+ if len(cols) != 2 {
+ log.Fatalf("bad passwords format: %s:%d", *passwords, n)
+ continue
+ }
+ if cols[0] != c.nickname {
+ continue
+ }
+ h := sha256.Sum256([]byte(c.password))
+ authenticated = subtle.ConstantTimeCompare(
+ []byte(hex.EncodeToString(h[:])),
+ []byte(cols[1]),
+ ) == 1
+ break
+ }
+ if !authenticated {
+ c.ReplyParts("462", "You may not register")
+ c.Close()
+ return
+ }
+ }
+ c.registered = true
+ c.ReplyNicknamed("001", "Hi, welcome to IRC")
+ c.ReplyNicknamed("002", "Your host is "+*hostname+", running goircd "+Version)
+ c.ReplyNicknamed("003", "This server was created sometime")
+ c.ReplyNicknamed("004", *hostname+" goircd o o")
+ c.SendLusers()
+ c.SendMotd()
+ if *verbose {
+ log.Println(c, "logged in")
+ }
+ }