- Timestamp:
- Mar 16, 2020, 3:16:27 PM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/downstream.go
r111 r112 3 3 import ( 4 4 "crypto/tls" 5 "encoding/base64" 5 6 "fmt" 6 7 "io" … … 11 12 "time" 12 13 14 "github.com/emersion/go-sasl" 13 15 "golang.org/x/crypto/bcrypt" 14 16 "gopkg.in/irc.v3" … … 76 78 capVersion int 77 79 caps map[string]bool 80 81 saslServer sasl.Server 78 82 79 83 lock sync.Mutex … … 343 347 return err 344 348 } 349 case "AUTHENTICATE": 350 if !dc.caps["sasl"] { 351 return ircError{&irc.Message{ 352 Command: err_saslfail, 353 Params: []string{"*", "AUTHENTICATE requires the \"sasl\" capability to be enabled"}, 354 }} 355 } 356 if len(msg.Params) == 0 { 357 return ircError{&irc.Message{ 358 Command: err_saslfail, 359 Params: []string{"*", "Missing AUTHENTICATE argument"}, 360 }} 361 } 362 if dc.nick == "" { 363 return ircError{&irc.Message{ 364 Command: err_saslfail, 365 Params: []string{"*", "Expected NICK command before AUTHENTICATE"}, 366 }} 367 } 368 369 var resp []byte 370 if dc.saslServer == nil { 371 mech := strings.ToUpper(msg.Params[0]) 372 switch mech { 373 case "PLAIN": 374 dc.saslServer = sasl.NewPlainServer(sasl.PlainAuthenticator(func(identity, username, password string) error { 375 return dc.authenticate(username, password) 376 })) 377 default: 378 return ircError{&irc.Message{ 379 Command: err_saslfail, 380 Params: []string{"*", fmt.Sprintf("Unsupported SASL mechanism %q", mech)}, 381 }} 382 } 383 } else if msg.Params[0] == "*" { 384 dc.saslServer = nil 385 return ircError{&irc.Message{ 386 Command: err_saslaborted, 387 Params: []string{"*", "SASL authentication aborted"}, 388 }} 389 } else if msg.Params[0] == "+" { 390 resp = nil 391 } else { 392 // TODO: multi-line messages 393 var err error 394 resp, err = base64.StdEncoding.DecodeString(msg.Params[0]) 395 if err != nil { 396 dc.saslServer = nil 397 return ircError{&irc.Message{ 398 Command: err_saslfail, 399 Params: []string{"*", "Invalid base64-encoded response"}, 400 }} 401 } 402 } 403 404 challenge, done, err := dc.saslServer.Next(resp) 405 if err != nil { 406 dc.saslServer = nil 407 if ircErr, ok := err.(ircError); ok && ircErr.Message.Command == irc.ERR_PASSWDMISMATCH { 408 return ircError{&irc.Message{ 409 Command: err_saslfail, 410 Params: []string{"*", ircErr.Message.Params[1]}, 411 }} 412 } 413 dc.SendMessage(&irc.Message{ 414 Prefix: dc.srv.prefix(), 415 Command: err_saslfail, 416 Params: []string{"*", "SASL error"}, 417 }) 418 return fmt.Errorf("SASL authentication failed: %v", err) 419 } else if done { 420 dc.saslServer = nil 421 dc.SendMessage(&irc.Message{ 422 Prefix: dc.srv.prefix(), 423 Command: rpl_loggedin, 424 Params: []string{dc.nick, dc.nick, dc.user.Username, "You are now logged in"}, 425 }) 426 dc.SendMessage(&irc.Message{ 427 Prefix: dc.srv.prefix(), 428 Command: rpl_saslsuccess, 429 Params: []string{dc.nick, "SASL authentication successful"}, 430 }) 431 } else { 432 challengeStr := "+" 433 if challenge != nil { 434 challengeStr = base64.StdEncoding.EncodeToString(challenge) 435 } 436 437 // TODO: multi-line messages 438 dc.SendMessage(&irc.Message{ 439 Prefix: dc.srv.prefix(), 440 Command: "AUTHENTICATE", 441 Params: []string{challengeStr}, 442 }) 443 } 345 444 default: 346 445 dc.logger.Printf("unhandled message: %v", msg) … … 371 470 372 471 var caps []string 373 /*if dc.capVersion >= 302 {472 if dc.capVersion >= 302 { 374 473 caps = append(caps, "sasl=PLAIN") 375 474 } else { 376 475 caps = append(caps, "sasl") 377 } */476 } 378 477 379 478 // TODO: multi-line replies … … 422 521 423 522 switch name { 424 /*case "sasl":425 dc.caps[name] = enable */523 case "sasl": 524 dc.caps[name] = enable 426 525 default: 427 526 ack = false … … 458 557 } 459 558 460 func (dc *downstreamConn) register() error { 461 username := dc.rawUsername 462 var networkName string 559 func unmarshalUsername(rawUsername string) (username, network string) { 560 username = rawUsername 463 561 if i := strings.LastIndexAny(username, "/@"); i >= 0 { 464 network Name= username[i+1:]562 network = username[i+1:] 465 563 } 466 564 if i := strings.IndexAny(username, "/@"); i >= 0 { 467 565 username = username[:i] 468 566 } 469 dc.username = "~" + username 470 471 password := dc.password 472 dc.password = "" 567 return username, network 568 } 569 570 func (dc *downstreamConn) setNetwork(networkName string) error { 571 if networkName == "" { 572 return nil 573 } 574 575 network := dc.user.getNetwork(networkName) 576 if network == nil { 577 addr := networkName 578 if !strings.ContainsRune(addr, ':') { 579 addr = addr + ":6697" 580 } 581 582 dc.logger.Printf("trying to connect to new network %q", addr) 583 if err := sanityCheckServer(addr); err != nil { 584 dc.logger.Printf("failed to connect to %q: %v", addr, err) 585 return ircError{&irc.Message{ 586 Command: irc.ERR_PASSWDMISMATCH, 587 Params: []string{"*", fmt.Sprintf("Failed to connect to %q", networkName)}, 588 }} 589 } 590 591 dc.logger.Printf("auto-saving network %q", networkName) 592 var err error 593 network, err = dc.user.createNetwork(networkName, dc.nick) 594 if err != nil { 595 return err 596 } 597 } 598 599 dc.network = network 600 return nil 601 } 602 603 func (dc *downstreamConn) authenticate(username, password string) error { 604 username, networkName := unmarshalUsername(username) 473 605 474 606 u := dc.srv.getUser(username) … … 484 616 } 485 617 486 var network *network 487 if networkName != "" { 488 network = u.getNetwork(networkName) 489 if network == nil { 490 addr := networkName 491 if !strings.ContainsRune(addr, ':') { 492 addr = addr + ":6697" 493 } 494 495 dc.logger.Printf("trying to connect to new network %q", addr) 496 if err := sanityCheckServer(addr); err != nil { 497 dc.logger.Printf("failed to connect to %q: %v", addr, err) 498 return ircError{&irc.Message{ 499 Command: irc.ERR_PASSWDMISMATCH, 500 Params: []string{"*", fmt.Sprintf("Failed to connect to %q", networkName)}, 501 }} 502 } 503 504 dc.logger.Printf("auto-saving network %q", networkName) 505 network, err = u.createNetwork(networkName, dc.nick) 506 if err != nil { 507 return err 508 } 618 dc.user = u 619 620 return dc.setNetwork(networkName) 621 } 622 623 func (dc *downstreamConn) register() error { 624 password := dc.password 625 dc.password = "" 626 if dc.user == nil { 627 if err := dc.authenticate(dc.rawUsername, password); err != nil { 628 return err 629 } 630 } else if dc.network == nil { 631 _, networkName := unmarshalUsername(dc.rawUsername) 632 if err := dc.setNetwork(networkName); err != nil { 633 return err 509 634 } 510 635 } 511 636 512 637 dc.registered = true 513 dc.user = u 514 dc.network = network 515 516 u.lock.Lock() 517 firstDownstream := len(u.downstreamConns) == 0 518 u.downstreamConns = append(u.downstreamConns, dc) 519 u.lock.Unlock() 638 dc.username = dc.user.Username 639 640 dc.user.lock.Lock() 641 firstDownstream := len(dc.user.downstreamConns) == 0 642 dc.user.downstreamConns = append(dc.user.downstreamConns, dc) 643 dc.user.lock.Unlock() 520 644 521 645 dc.SendMessage(&irc.Message{
Note:
See TracChangeset
for help on using the changeset viewer.