github.com/roboticscm/goman@v0.0.0-20210203095141-87c07b4a0a55/src/net/smtp/smtp_test.go (about)

     1  // Copyright 2010 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package smtp
     6  
     7  import (
     8  	"bufio"
     9  	"bytes"
    10  	"crypto/tls"
    11  	"crypto/x509"
    12  	"io"
    13  	"net"
    14  	"net/textproto"
    15  	"strings"
    16  	"testing"
    17  	"time"
    18  )
    19  
    20  type authTest struct {
    21  	auth       Auth
    22  	challenges []string
    23  	name       string
    24  	responses  []string
    25  }
    26  
    27  var authTests = []authTest{
    28  	{PlainAuth("", "user", "pass", "testserver"), []string{}, "PLAIN", []string{"\x00user\x00pass"}},
    29  	{PlainAuth("foo", "bar", "baz", "testserver"), []string{}, "PLAIN", []string{"foo\x00bar\x00baz"}},
    30  	{CRAMMD5Auth("user", "pass"), []string{"<123456.1322876914@testserver>"}, "CRAM-MD5", []string{"", "user 287eb355114cf5c471c26a875f1ca4ae"}},
    31  }
    32  
    33  func TestAuth(t *testing.T) {
    34  testLoop:
    35  	for i, test := range authTests {
    36  		name, resp, err := test.auth.Start(&ServerInfo{"testserver", true, nil})
    37  		if name != test.name {
    38  			t.Errorf("#%d got name %s, expected %s", i, name, test.name)
    39  		}
    40  		if !bytes.Equal(resp, []byte(test.responses[0])) {
    41  			t.Errorf("#%d got response %s, expected %s", i, resp, test.responses[0])
    42  		}
    43  		if err != nil {
    44  			t.Errorf("#%d error: %s", i, err)
    45  		}
    46  		for j := range test.challenges {
    47  			challenge := []byte(test.challenges[j])
    48  			expected := []byte(test.responses[j+1])
    49  			resp, err := test.auth.Next(challenge, true)
    50  			if err != nil {
    51  				t.Errorf("#%d error: %s", i, err)
    52  				continue testLoop
    53  			}
    54  			if !bytes.Equal(resp, expected) {
    55  				t.Errorf("#%d got %s, expected %s", i, resp, expected)
    56  				continue testLoop
    57  			}
    58  		}
    59  	}
    60  }
    61  
    62  func TestAuthPlain(t *testing.T) {
    63  	auth := PlainAuth("foo", "bar", "baz", "servername")
    64  
    65  	tests := []struct {
    66  		server *ServerInfo
    67  		err    string
    68  	}{
    69  		{
    70  			server: &ServerInfo{Name: "servername", TLS: true},
    71  		},
    72  		{
    73  			// Okay; explicitly advertised by server.
    74  			server: &ServerInfo{Name: "servername", Auth: []string{"PLAIN"}},
    75  		},
    76  		{
    77  			server: &ServerInfo{Name: "servername", Auth: []string{"CRAM-MD5"}},
    78  			err:    "unencrypted connection",
    79  		},
    80  		{
    81  			server: &ServerInfo{Name: "attacker", TLS: true},
    82  			err:    "wrong host name",
    83  		},
    84  	}
    85  	for i, tt := range tests {
    86  		_, _, err := auth.Start(tt.server)
    87  		got := ""
    88  		if err != nil {
    89  			got = err.Error()
    90  		}
    91  		if got != tt.err {
    92  			t.Errorf("%d. got error = %q; want %q", i, got, tt.err)
    93  		}
    94  	}
    95  }
    96  
    97  type faker struct {
    98  	io.ReadWriter
    99  }
   100  
   101  func (f faker) Close() error                     { return nil }
   102  func (f faker) LocalAddr() net.Addr              { return nil }
   103  func (f faker) RemoteAddr() net.Addr             { return nil }
   104  func (f faker) SetDeadline(time.Time) error      { return nil }
   105  func (f faker) SetReadDeadline(time.Time) error  { return nil }
   106  func (f faker) SetWriteDeadline(time.Time) error { return nil }
   107  
   108  func TestBasic(t *testing.T) {
   109  	server := strings.Join(strings.Split(basicServer, "\n"), "\r\n")
   110  	client := strings.Join(strings.Split(basicClient, "\n"), "\r\n")
   111  
   112  	var cmdbuf bytes.Buffer
   113  	bcmdbuf := bufio.NewWriter(&cmdbuf)
   114  	var fake faker
   115  	fake.ReadWriter = bufio.NewReadWriter(bufio.NewReader(strings.NewReader(server)), bcmdbuf)
   116  	c := &Client{Text: textproto.NewConn(fake), localName: "localhost"}
   117  
   118  	if err := c.helo(); err != nil {
   119  		t.Fatalf("HELO failed: %s", err)
   120  	}
   121  	if err := c.ehlo(); err == nil {
   122  		t.Fatalf("Expected first EHLO to fail")
   123  	}
   124  	if err := c.ehlo(); err != nil {
   125  		t.Fatalf("Second EHLO failed: %s", err)
   126  	}
   127  
   128  	c.didHello = true
   129  	if ok, args := c.Extension("aUtH"); !ok || args != "LOGIN PLAIN" {
   130  		t.Fatalf("Expected AUTH supported")
   131  	}
   132  	if ok, _ := c.Extension("DSN"); ok {
   133  		t.Fatalf("Shouldn't support DSN")
   134  	}
   135  
   136  	if err := c.Mail("user@gmail.com"); err == nil {
   137  		t.Fatalf("MAIL should require authentication")
   138  	}
   139  
   140  	if err := c.Verify("user1@gmail.com"); err == nil {
   141  		t.Fatalf("First VRFY: expected no verification")
   142  	}
   143  	if err := c.Verify("user2@gmail.com"); err != nil {
   144  		t.Fatalf("Second VRFY: expected verification, got %s", err)
   145  	}
   146  
   147  	// fake TLS so authentication won't complain
   148  	c.tls = true
   149  	c.serverName = "smtp.google.com"
   150  	if err := c.Auth(PlainAuth("", "user", "pass", "smtp.google.com")); err != nil {
   151  		t.Fatalf("AUTH failed: %s", err)
   152  	}
   153  
   154  	if err := c.Mail("user@gmail.com"); err != nil {
   155  		t.Fatalf("MAIL failed: %s", err)
   156  	}
   157  	if err := c.Rcpt("golang-nuts@googlegroups.com"); err != nil {
   158  		t.Fatalf("RCPT failed: %s", err)
   159  	}
   160  	msg := `From: user@gmail.com
   161  To: golang-nuts@googlegroups.com
   162  Subject: Hooray for Go
   163  
   164  Line 1
   165  .Leading dot line .
   166  Goodbye.`
   167  	w, err := c.Data()
   168  	if err != nil {
   169  		t.Fatalf("DATA failed: %s", err)
   170  	}
   171  	if _, err := w.Write([]byte(msg)); err != nil {
   172  		t.Fatalf("Data write failed: %s", err)
   173  	}
   174  	if err := w.Close(); err != nil {
   175  		t.Fatalf("Bad data response: %s", err)
   176  	}
   177  
   178  	if err := c.Quit(); err != nil {
   179  		t.Fatalf("QUIT failed: %s", err)
   180  	}
   181  
   182  	bcmdbuf.Flush()
   183  	actualcmds := cmdbuf.String()
   184  	if client != actualcmds {
   185  		t.Fatalf("Got:\n%s\nExpected:\n%s", actualcmds, client)
   186  	}
   187  }
   188  
   189  var basicServer = `250 mx.google.com at your service
   190  502 Unrecognized command.
   191  250-mx.google.com at your service
   192  250-SIZE 35651584
   193  250-AUTH LOGIN PLAIN
   194  250 8BITMIME
   195  530 Authentication required
   196  252 Send some mail, I'll try my best
   197  250 User is valid
   198  235 Accepted
   199  250 Sender OK
   200  250 Receiver OK
   201  354 Go ahead
   202  250 Data OK
   203  221 OK
   204  `
   205  
   206  var basicClient = `HELO localhost
   207  EHLO localhost
   208  EHLO localhost
   209  MAIL FROM:<user@gmail.com> BODY=8BITMIME
   210  VRFY user1@gmail.com
   211  VRFY user2@gmail.com
   212  AUTH PLAIN AHVzZXIAcGFzcw==
   213  MAIL FROM:<user@gmail.com> BODY=8BITMIME
   214  RCPT TO:<golang-nuts@googlegroups.com>
   215  DATA
   216  From: user@gmail.com
   217  To: golang-nuts@googlegroups.com
   218  Subject: Hooray for Go
   219  
   220  Line 1
   221  ..Leading dot line .
   222  Goodbye.
   223  .
   224  QUIT
   225  `
   226  
   227  func TestNewClient(t *testing.T) {
   228  	server := strings.Join(strings.Split(newClientServer, "\n"), "\r\n")
   229  	client := strings.Join(strings.Split(newClientClient, "\n"), "\r\n")
   230  
   231  	var cmdbuf bytes.Buffer
   232  	bcmdbuf := bufio.NewWriter(&cmdbuf)
   233  	out := func() string {
   234  		bcmdbuf.Flush()
   235  		return cmdbuf.String()
   236  	}
   237  	var fake faker
   238  	fake.ReadWriter = bufio.NewReadWriter(bufio.NewReader(strings.NewReader(server)), bcmdbuf)
   239  	c, err := NewClient(fake, "fake.host")
   240  	if err != nil {
   241  		t.Fatalf("NewClient: %v\n(after %v)", err, out())
   242  	}
   243  	defer c.Close()
   244  	if ok, args := c.Extension("aUtH"); !ok || args != "LOGIN PLAIN" {
   245  		t.Fatalf("Expected AUTH supported")
   246  	}
   247  	if ok, _ := c.Extension("DSN"); ok {
   248  		t.Fatalf("Shouldn't support DSN")
   249  	}
   250  	if err := c.Quit(); err != nil {
   251  		t.Fatalf("QUIT failed: %s", err)
   252  	}
   253  
   254  	actualcmds := out()
   255  	if client != actualcmds {
   256  		t.Fatalf("Got:\n%s\nExpected:\n%s", actualcmds, client)
   257  	}
   258  }
   259  
   260  var newClientServer = `220 hello world
   261  250-mx.google.com at your service
   262  250-SIZE 35651584
   263  250-AUTH LOGIN PLAIN
   264  250 8BITMIME
   265  221 OK
   266  `
   267  
   268  var newClientClient = `EHLO localhost
   269  QUIT
   270  `
   271  
   272  func TestNewClient2(t *testing.T) {
   273  	server := strings.Join(strings.Split(newClient2Server, "\n"), "\r\n")
   274  	client := strings.Join(strings.Split(newClient2Client, "\n"), "\r\n")
   275  
   276  	var cmdbuf bytes.Buffer
   277  	bcmdbuf := bufio.NewWriter(&cmdbuf)
   278  	var fake faker
   279  	fake.ReadWriter = bufio.NewReadWriter(bufio.NewReader(strings.NewReader(server)), bcmdbuf)
   280  	c, err := NewClient(fake, "fake.host")
   281  	if err != nil {
   282  		t.Fatalf("NewClient: %v", err)
   283  	}
   284  	defer c.Close()
   285  	if ok, _ := c.Extension("DSN"); ok {
   286  		t.Fatalf("Shouldn't support DSN")
   287  	}
   288  	if err := c.Quit(); err != nil {
   289  		t.Fatalf("QUIT failed: %s", err)
   290  	}
   291  
   292  	bcmdbuf.Flush()
   293  	actualcmds := cmdbuf.String()
   294  	if client != actualcmds {
   295  		t.Fatalf("Got:\n%s\nExpected:\n%s", actualcmds, client)
   296  	}
   297  }
   298  
   299  var newClient2Server = `220 hello world
   300  502 EH?
   301  250-mx.google.com at your service
   302  250-SIZE 35651584
   303  250-AUTH LOGIN PLAIN
   304  250 8BITMIME
   305  221 OK
   306  `
   307  
   308  var newClient2Client = `EHLO localhost
   309  HELO localhost
   310  QUIT
   311  `
   312  
   313  func TestHello(t *testing.T) {
   314  
   315  	if len(helloServer) != len(helloClient) {
   316  		t.Fatalf("Hello server and client size mismatch")
   317  	}
   318  
   319  	for i := 0; i < len(helloServer); i++ {
   320  		server := strings.Join(strings.Split(baseHelloServer+helloServer[i], "\n"), "\r\n")
   321  		client := strings.Join(strings.Split(baseHelloClient+helloClient[i], "\n"), "\r\n")
   322  		var cmdbuf bytes.Buffer
   323  		bcmdbuf := bufio.NewWriter(&cmdbuf)
   324  		var fake faker
   325  		fake.ReadWriter = bufio.NewReadWriter(bufio.NewReader(strings.NewReader(server)), bcmdbuf)
   326  		c, err := NewClient(fake, "fake.host")
   327  		if err != nil {
   328  			t.Fatalf("NewClient: %v", err)
   329  		}
   330  		defer c.Close()
   331  		c.localName = "customhost"
   332  		err = nil
   333  
   334  		switch i {
   335  		case 0:
   336  			err = c.Hello("customhost")
   337  		case 1:
   338  			err = c.StartTLS(nil)
   339  			if err.Error() == "502 Not implemented" {
   340  				err = nil
   341  			}
   342  		case 2:
   343  			err = c.Verify("test@example.com")
   344  		case 3:
   345  			c.tls = true
   346  			c.serverName = "smtp.google.com"
   347  			err = c.Auth(PlainAuth("", "user", "pass", "smtp.google.com"))
   348  		case 4:
   349  			err = c.Mail("test@example.com")
   350  		case 5:
   351  			ok, _ := c.Extension("feature")
   352  			if ok {
   353  				t.Errorf("Expected FEATURE not to be supported")
   354  			}
   355  		case 6:
   356  			err = c.Reset()
   357  		case 7:
   358  			err = c.Quit()
   359  		case 8:
   360  			err = c.Verify("test@example.com")
   361  			if err != nil {
   362  				err = c.Hello("customhost")
   363  				if err != nil {
   364  					t.Errorf("Want error, got none")
   365  				}
   366  			}
   367  		default:
   368  			t.Fatalf("Unhandled command")
   369  		}
   370  
   371  		if err != nil {
   372  			t.Errorf("Command %d failed: %v", i, err)
   373  		}
   374  
   375  		bcmdbuf.Flush()
   376  		actualcmds := cmdbuf.String()
   377  		if client != actualcmds {
   378  			t.Errorf("Got:\n%s\nExpected:\n%s", actualcmds, client)
   379  		}
   380  	}
   381  }
   382  
   383  var baseHelloServer = `220 hello world
   384  502 EH?
   385  250-mx.google.com at your service
   386  250 FEATURE
   387  `
   388  
   389  var helloServer = []string{
   390  	"",
   391  	"502 Not implemented\n",
   392  	"250 User is valid\n",
   393  	"235 Accepted\n",
   394  	"250 Sender ok\n",
   395  	"",
   396  	"250 Reset ok\n",
   397  	"221 Goodbye\n",
   398  	"250 Sender ok\n",
   399  }
   400  
   401  var baseHelloClient = `EHLO customhost
   402  HELO customhost
   403  `
   404  
   405  var helloClient = []string{
   406  	"",
   407  	"STARTTLS\n",
   408  	"VRFY test@example.com\n",
   409  	"AUTH PLAIN AHVzZXIAcGFzcw==\n",
   410  	"MAIL FROM:<test@example.com>\n",
   411  	"",
   412  	"RSET\n",
   413  	"QUIT\n",
   414  	"VRFY test@example.com\n",
   415  }
   416  
   417  func TestSendMail(t *testing.T) {
   418  	server := strings.Join(strings.Split(sendMailServer, "\n"), "\r\n")
   419  	client := strings.Join(strings.Split(sendMailClient, "\n"), "\r\n")
   420  	var cmdbuf bytes.Buffer
   421  	bcmdbuf := bufio.NewWriter(&cmdbuf)
   422  	l, err := net.Listen("tcp", "127.0.0.1:0")
   423  	if err != nil {
   424  		t.Fatalf("Unable to to create listener: %v", err)
   425  	}
   426  	defer l.Close()
   427  
   428  	// prevent data race on bcmdbuf
   429  	var done = make(chan struct{})
   430  	go func(data []string) {
   431  
   432  		defer close(done)
   433  
   434  		conn, err := l.Accept()
   435  		if err != nil {
   436  			t.Errorf("Accept error: %v", err)
   437  			return
   438  		}
   439  		defer conn.Close()
   440  
   441  		tc := textproto.NewConn(conn)
   442  		for i := 0; i < len(data) && data[i] != ""; i++ {
   443  			tc.PrintfLine(data[i])
   444  			for len(data[i]) >= 4 && data[i][3] == '-' {
   445  				i++
   446  				tc.PrintfLine(data[i])
   447  			}
   448  			if data[i] == "221 Goodbye" {
   449  				return
   450  			}
   451  			read := false
   452  			for !read || data[i] == "354 Go ahead" {
   453  				msg, err := tc.ReadLine()
   454  				bcmdbuf.Write([]byte(msg + "\r\n"))
   455  				read = true
   456  				if err != nil {
   457  					t.Errorf("Read error: %v", err)
   458  					return
   459  				}
   460  				if data[i] == "354 Go ahead" && msg == "." {
   461  					break
   462  				}
   463  			}
   464  		}
   465  	}(strings.Split(server, "\r\n"))
   466  
   467  	err = SendMail(l.Addr().String(), nil, "test@example.com", []string{"other@example.com"}, []byte(strings.Replace(`From: test@example.com
   468  To: other@example.com
   469  Subject: SendMail test
   470  
   471  SendMail is working for me.
   472  `, "\n", "\r\n", -1)))
   473  
   474  	if err != nil {
   475  		t.Errorf("%v", err)
   476  	}
   477  
   478  	<-done
   479  	bcmdbuf.Flush()
   480  	actualcmds := cmdbuf.String()
   481  	if client != actualcmds {
   482  		t.Errorf("Got:\n%s\nExpected:\n%s", actualcmds, client)
   483  	}
   484  }
   485  
   486  var sendMailServer = `220 hello world
   487  502 EH?
   488  250 mx.google.com at your service
   489  250 Sender ok
   490  250 Receiver ok
   491  354 Go ahead
   492  250 Data ok
   493  221 Goodbye
   494  `
   495  
   496  var sendMailClient = `EHLO localhost
   497  HELO localhost
   498  MAIL FROM:<test@example.com>
   499  RCPT TO:<other@example.com>
   500  DATA
   501  From: test@example.com
   502  To: other@example.com
   503  Subject: SendMail test
   504  
   505  SendMail is working for me.
   506  .
   507  QUIT
   508  `
   509  
   510  func TestAuthFailed(t *testing.T) {
   511  	server := strings.Join(strings.Split(authFailedServer, "\n"), "\r\n")
   512  	client := strings.Join(strings.Split(authFailedClient, "\n"), "\r\n")
   513  	var cmdbuf bytes.Buffer
   514  	bcmdbuf := bufio.NewWriter(&cmdbuf)
   515  	var fake faker
   516  	fake.ReadWriter = bufio.NewReadWriter(bufio.NewReader(strings.NewReader(server)), bcmdbuf)
   517  	c, err := NewClient(fake, "fake.host")
   518  	if err != nil {
   519  		t.Fatalf("NewClient: %v", err)
   520  	}
   521  	defer c.Close()
   522  
   523  	c.tls = true
   524  	c.serverName = "smtp.google.com"
   525  	err = c.Auth(PlainAuth("", "user", "pass", "smtp.google.com"))
   526  
   527  	if err == nil {
   528  		t.Error("Auth: expected error; got none")
   529  	} else if err.Error() != "535 Invalid credentials\nplease see www.example.com" {
   530  		t.Errorf("Auth: got error: %v, want: %s", err, "535 Invalid credentials\nplease see www.example.com")
   531  	}
   532  
   533  	bcmdbuf.Flush()
   534  	actualcmds := cmdbuf.String()
   535  	if client != actualcmds {
   536  		t.Errorf("Got:\n%s\nExpected:\n%s", actualcmds, client)
   537  	}
   538  }
   539  
   540  var authFailedServer = `220 hello world
   541  250-mx.google.com at your service
   542  250 AUTH LOGIN PLAIN
   543  535-Invalid credentials
   544  535 please see www.example.com
   545  221 Goodbye
   546  `
   547  
   548  var authFailedClient = `EHLO localhost
   549  AUTH PLAIN AHVzZXIAcGFzcw==
   550  *
   551  QUIT
   552  `
   553  
   554  func TestTLSClient(t *testing.T) {
   555  	ln := newLocalListener(t)
   556  	defer ln.Close()
   557  	errc := make(chan error)
   558  	go func() {
   559  		errc <- sendMail(ln.Addr().String())
   560  	}()
   561  	conn, err := ln.Accept()
   562  	if err != nil {
   563  		t.Fatalf("failed to accept connection: %v", err)
   564  	}
   565  	defer conn.Close()
   566  	if err := serverHandle(conn, t); err != nil {
   567  		t.Fatalf("failed to handle connection: %v", err)
   568  	}
   569  	if err := <-errc; err != nil {
   570  		t.Fatalf("client error: %v", err)
   571  	}
   572  }
   573  
   574  func newLocalListener(t *testing.T) net.Listener {
   575  	ln, err := net.Listen("tcp", "127.0.0.1:0")
   576  	if err != nil {
   577  		ln, err = net.Listen("tcp6", "[::1]:0")
   578  	}
   579  	if err != nil {
   580  		t.Fatal(err)
   581  	}
   582  	return ln
   583  }
   584  
   585  type smtpSender struct {
   586  	w io.Writer
   587  }
   588  
   589  func (s smtpSender) send(f string) {
   590  	s.w.Write([]byte(f + "\r\n"))
   591  }
   592  
   593  // smtp server, finely tailored to deal with our own client only!
   594  func serverHandle(c net.Conn, t *testing.T) error {
   595  	send := smtpSender{c}.send
   596  	send("220 127.0.0.1 ESMTP service ready")
   597  	s := bufio.NewScanner(c)
   598  	for s.Scan() {
   599  		switch s.Text() {
   600  		case "EHLO localhost":
   601  			send("250-127.0.0.1 ESMTP offers a warm hug of welcome")
   602  			send("250-STARTTLS")
   603  			send("250 Ok")
   604  		case "STARTTLS":
   605  			send("220 Go ahead")
   606  			keypair, err := tls.X509KeyPair(localhostCert, localhostKey)
   607  			if err != nil {
   608  				return err
   609  			}
   610  			config := &tls.Config{Certificates: []tls.Certificate{keypair}}
   611  			c = tls.Server(c, config)
   612  			defer c.Close()
   613  			return serverHandleTLS(c, t)
   614  		default:
   615  			t.Fatalf("unrecognized command: %q", s.Text())
   616  		}
   617  	}
   618  	return s.Err()
   619  }
   620  
   621  func serverHandleTLS(c net.Conn, t *testing.T) error {
   622  	send := smtpSender{c}.send
   623  	s := bufio.NewScanner(c)
   624  	for s.Scan() {
   625  		switch s.Text() {
   626  		case "EHLO localhost":
   627  			send("250 Ok")
   628  		case "MAIL FROM:<joe1@example.com>":
   629  			send("250 Ok")
   630  		case "RCPT TO:<joe2@example.com>":
   631  			send("250 Ok")
   632  		case "DATA":
   633  			send("354 send the mail data, end with .")
   634  			send("250 Ok")
   635  		case "Subject: test":
   636  		case "":
   637  		case "howdy!":
   638  		case ".":
   639  		case "QUIT":
   640  			send("221 127.0.0.1 Service closing transmission channel")
   641  			return nil
   642  		default:
   643  			t.Fatalf("unrecognized command during TLS: %q", s.Text())
   644  		}
   645  	}
   646  	return s.Err()
   647  }
   648  
   649  func init() {
   650  	testRootCAs := x509.NewCertPool()
   651  	testRootCAs.AppendCertsFromPEM(localhostCert)
   652  	testHookStartTLS = func(config *tls.Config) {
   653  		config.RootCAs = testRootCAs
   654  	}
   655  }
   656  
   657  func sendMail(hostPort string) error {
   658  	host, _, err := net.SplitHostPort(hostPort)
   659  	if err != nil {
   660  		return err
   661  	}
   662  	auth := PlainAuth("", "", "", host)
   663  	from := "joe1@example.com"
   664  	to := []string{"joe2@example.com"}
   665  	return SendMail(hostPort, auth, from, to, []byte("Subject: test\n\nhowdy!"))
   666  }
   667  
   668  // (copied from net/http/httptest)
   669  // localhostCert is a PEM-encoded TLS cert with SAN IPs
   670  // "127.0.0.1" and "[::1]", expiring at the last second of 2049 (the end
   671  // of ASN.1 time).
   672  // generated from src/crypto/tls:
   673  // go run generate_cert.go  --rsa-bits 512 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
   674  var localhostCert = []byte(`-----BEGIN CERTIFICATE-----
   675  MIIBdzCCASOgAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD
   676  bzAeFw03MDAxMDEwMDAwMDBaFw00OTEyMzEyMzU5NTlaMBIxEDAOBgNVBAoTB0Fj
   677  bWUgQ28wWjALBgkqhkiG9w0BAQEDSwAwSAJBAN55NcYKZeInyTuhcCwFMhDHCmwa
   678  IUSdtXdcbItRB/yfXGBhiex00IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEA
   679  AaNoMGYwDgYDVR0PAQH/BAQDAgCkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1Ud
   680  EwEB/wQFMAMBAf8wLgYDVR0RBCcwJYILZXhhbXBsZS5jb22HBH8AAAGHEAAAAAAA
   681  AAAAAAAAAAAAAAEwCwYJKoZIhvcNAQEFA0EAAoQn/ytgqpiLcZu9XKbCJsJcvkgk
   682  Se6AbGXgSlq+ZCEVo0qIwSgeBqmsJxUu7NCSOwVJLYNEBO2DtIxoYVk+MA==
   683  -----END CERTIFICATE-----`)
   684  
   685  // localhostKey is the private key for localhostCert.
   686  var localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
   687  MIIBPAIBAAJBAN55NcYKZeInyTuhcCwFMhDHCmwaIUSdtXdcbItRB/yfXGBhiex0
   688  0IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEAAQJBAQdUx66rfh8sYsgfdcvV
   689  NoafYpnEcB5s4m/vSVe6SU7dCK6eYec9f9wpT353ljhDUHq3EbmE4foNzJngh35d
   690  AekCIQDhRQG5Li0Wj8TM4obOnnXUXf1jRv0UkzE9AHWLG5q3AwIhAPzSjpYUDjVW
   691  MCUXgckTpKCuGwbJk7424Nb8bLzf3kllAiA5mUBgjfr/WtFSJdWcPQ4Zt9KTMNKD
   692  EUO0ukpTwEIl6wIhAMbGqZK3zAAFdq8DD2jPx+UJXnh0rnOkZBzDtJ6/iN69AiEA
   693  1Aq8MJgTaYsDQWyU/hDq5YkDJc9e9DSCvUIzqxQWMQE=
   694  -----END RSA PRIVATE KEY-----`)