// Copyright 2010 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package smtpimport ()// Auth is implemented by an SMTP authentication mechanism.typeAuthinterface {// Start begins an authentication with a server. // It returns the name of the authentication protocol // and optionally data to include in the initial AUTH message // sent to the server. // If it returns a non-nil error, the SMTP client aborts // the authentication attempt and closes the connection.Start(server *ServerInfo) (proto string, toServer []byte, err error)// Next continues the authentication. The server has just sent // the fromServer data. If more is true, the server expects a // response, which Next should return as toServer; otherwise // Next should return toServer == nil. // If Next returns a non-nil error, the SMTP client aborts // the authentication attempt and closes the connection.Next(fromServer []byte, more bool) (toServer []byte, err error)}// ServerInfo records information about an SMTP server.typeServerInfostruct { Name string// SMTP server name TLS bool// using TLS, with valid certificate for Name Auth []string// advertised authentication mechanisms}type plainAuth struct { identity, username, password string host string}// PlainAuth returns an [Auth] that implements the PLAIN authentication// mechanism as defined in RFC 4616. The returned Auth uses the given// username and password to authenticate to host and act as identity.// Usually identity should be the empty string, to act as username.//// PlainAuth will only send the credentials if the connection is using TLS// or is connected to localhost. Otherwise authentication will fail with an// error, without sending the credentials.func (, , , string) Auth {return &plainAuth{, , , }}func isLocalhost( string) bool {return == "localhost" || == "127.0.0.1" || == "::1"}func ( *plainAuth) ( *ServerInfo) (string, []byte, error) {// Must have TLS, or else localhost server. // Note: If TLS is not true, then we can't trust ANYTHING in ServerInfo. // In particular, it doesn't matter if the server advertises PLAIN auth. // That might just be the attacker saying // "it's ok, you can trust me with your password."if !.TLS && !isLocalhost(.Name) {return"", nil, errors.New("unencrypted connection") }if .Name != .host {return"", nil, errors.New("wrong host name") } := []byte(.identity + "\x00" + .username + "\x00" + .password)return"PLAIN", , nil}func ( *plainAuth) ( []byte, bool) ([]byte, error) {if {// We've already sent everything.returnnil, errors.New("unexpected server challenge") }returnnil, nil}type cramMD5Auth struct { username, secret string}// CRAMMD5Auth returns an [Auth] that implements the CRAM-MD5 authentication// mechanism as defined in RFC 2195.// The returned Auth uses the given username and secret to authenticate// to the server using the challenge-response mechanism.func (, string) Auth {return &cramMD5Auth{, }}func ( *cramMD5Auth) ( *ServerInfo) (string, []byte, error) {return"CRAM-MD5", nil, nil}func ( *cramMD5Auth) ( []byte, bool) ([]byte, error) {if { := hmac.New(md5.New, []byte(.secret)) .Write() := make([]byte, 0, .Size())returnfmt.Appendf(nil, "%s %x", .username, .Sum()), nil }returnnil, nil}
The pages are generated with Goldsv0.7.9-preview. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.