set priority to optional (was extra)
[debian/orchestra.git] / src / conductor / server.go
1 /* server.go
2  *
3  * TLS and Connection Hell.
4 */
5
6 package main
7
8 import (
9         "net"
10         "crypto/tls"
11         "fmt"
12         "os"
13         "crypto/x509"
14         o       "orchestra"
15 )
16
17 var (
18         CACertPool      *x509.CertPool = nil
19 )
20
21
22 func ServiceRequests() {
23         var sockConfig tls.Config
24
25         // resolve the bind address
26         bindAddressStr := GetStringOpt("bind address")
27         var bindAddr *net.IPAddr = nil
28         if (bindAddressStr != "") {
29                 var err os.Error
30                 bindAddr, err = net.ResolveIPAddr("ip", bindAddressStr)
31                 if (err != nil) {
32                         o.Warn("Ignoring bind address.  Couldn't resolve \"%s\": %s", bindAddressStr, err)
33                 } else {
34                         bindAddr = nil
35                 }
36         }
37         // load the x509 certificate and key, then attach it to the tls config.
38         x509CertFilename := GetStringOpt("x509 certificate")
39         x509PrivateKeyFilename := GetStringOpt("x509 private key")
40         serverCert, err := tls.LoadX509KeyPair(x509CertFilename, x509PrivateKeyFilename)
41         o.MightFail(err, "Couldn't load certificates")
42         sockConfig.Certificates = append(sockConfig.Certificates, serverCert)
43
44         // load the CA certs
45         CACertPool = x509.NewCertPool()
46         caCertNames := GetCACertList()
47         if caCertNames != nil {
48                 for _, filename := range caCertNames {
49                         fh, err := os.Open(filename)
50                         if err != nil {
51                                 o.Warn("Whilst parsing CA certs, couldn't open %s: %s", filename, err)
52                                 continue
53                         }
54                         defer fh.Close()
55                         fi, err := fh.Stat()
56                         o.MightFail(err, "Couldn't stat CA certificate file: %s", filename)
57                         data := make([]byte, fi.Size)
58                         fh.Read(data)
59                         CACertPool.AppendCertsFromPEM(data)
60                 }
61         }
62         sockConfig.RootCAs = CACertPool
63
64         // determine the server hostname.
65         servername := GetStringOpt("server name")
66         if servername != "" {
67                 o.Info("Using %s as the server name", servername)
68                 sockConfig.ServerName = servername
69         } else {
70                 if bindAddr != nil {
71                         o.Warn("Probing for fqdn for bind address as none was provided.")
72                         hostnames, err := net.LookupAddr(bindAddr.String())
73                         o.MightFail(err, "Failed to get full hostname for bind address")
74                         sockConfig.ServerName = hostnames[0]
75                 } else {
76                         o.Warn("Probing for fqdn as no server name was provided")
77                         sockConfig.ServerName = o.ProbeHostname()
78                 }
79         }
80
81         // ask the client to authenticate
82         sockConfig.AuthenticateClient = true
83
84         /* convert the bindAddress to a string suitable for the Listen call */
85         var laddr string
86         if (bindAddr == nil) {
87                 laddr = fmt.Sprintf(":%d", o.DefaultMasterPort)
88         } else {
89                 laddr = fmt.Sprintf("%s:%d", bindAddr.String(), o.DefaultMasterPort)
90         }
91         o.Info("Binding to %s", laddr)
92         listener, err := tls.Listen("tcp", laddr, &sockConfig)
93         o.MightFail(err, "Couldn't bind TLS listener")
94
95         for {
96                 o.Warn("Waiting for Connection...")
97                 c, err := listener.Accept()
98                 o.MightFail(err, "Couldn't accept TLS connection")
99                 o.Warn("Connection received from %s", c.RemoteAddr().String())
100                 HandleConnection(c)
101         }
102 }
103
104
105