github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/go/support_infrastructure/domain_service/domain_server/domain_server.go (about)

     1  // Copyright (c) 2016, Google Inc. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //     http://www.apache.org/licenses/LICENSE-2.0
     7  // Unless required by applicable law or agreed to in writing, software
     8  // distributed under the License is distributed on an "AS IS" BASIS,
     9  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    10  // See the License for the specific language governing permissions and
    11  // limitations under the License.
    12  
    13  package main
    14  
    15  import (
    16  	"crypto/x509"
    17  	"crypto/x509/pkix"
    18  	"errors"
    19  	"flag"
    20  	"fmt"
    21  	"io/ioutil"
    22  	"log"
    23  	"net"
    24  	"syscall"
    25  	"time"
    26  
    27  	"github.com/golang/protobuf/proto"
    28  	"github.com/jlmucb/cloudproxy/go/tao"
    29  	"github.com/jlmucb/cloudproxy/go/util"
    30  
    31  	// "github.com/golang/crypto/ssh/terminal"
    32  	"golang.org/x/crypto/ssh/terminal"
    33  
    34  	"github.com/jlmucb/cloudproxy/go/support_infrastructure/domain_service"
    35  )
    36  
    37  var network = flag.String("network", "tcp", "The network to use for connections")
    38  var addr = flag.String("addr", "localhost:8124", "The address to listen on")
    39  var domainPass = flag.String("pass", "", "The domain password")
    40  var configTemplate = flag.String("config_template", "./domain_template", "The Tao domain template")
    41  var configPath = flag.String("domain_config", "./tao.config", "The Tao domain config file")
    42  var trustedEntitiesPath = flag.String("trusted_entities", "./TrustedEntities", "File containing trusted entities.")
    43  var createDomainFlag = flag.Bool("create_domain", false, "To create new domain from specified config.")
    44  
    45  var serialNumber = 0
    46  var revokedCertificates []pkix.RevokedCertificate
    47  
    48  func getPass() []byte {
    49  	if domainPass == nil || *domainPass == "" {
    50  		// Get the password from the user.
    51  		fmt.Print("Policy key password: ")
    52  		pwd, err := terminal.ReadPassword(syscall.Stdin)
    53  		if err != nil {
    54  			log.Fatalln("Can't get password", err)
    55  		}
    56  		fmt.Println()
    57  		return pwd
    58  	} else {
    59  		fmt.Println("Warning: Passwords on the command line are not secure." +
    60  			"Use -pass option only for testing.")
    61  		return []byte(*domainPass)
    62  	}
    63  }
    64  
    65  func createDomain() (*tao.Domain, *x509.CertPool, error) {
    66  	var cfg tao.DomainTemplate
    67  	d, err := ioutil.ReadFile(*configTemplate)
    68  	if err != nil {
    69  		return nil, nil, err
    70  	}
    71  	if err := proto.UnmarshalText(string(d), &cfg); err != nil {
    72  		return nil, nil, err
    73  	}
    74  	pwd := getPass()
    75  	domain, err := tao.CreateDomain(*cfg.Config, *configPath, pwd)
    76  	if domain == nil {
    77  		log.Printf("domainserver: no domain path - %s, pass - %s, err - %s\n",
    78  			*configPath, pwd, err)
    79  		return nil, nil, err
    80  	} else if err != nil {
    81  		log.Printf("domainserver: Couldn't load the config path %s: %s\n",
    82  			*configPath, err)
    83  		return nil, nil, err
    84  	}
    85  	log.Printf("domainserver: Created domain\n")
    86  	err = domain.Save()
    87  	if err != nil {
    88  		return nil, nil, err
    89  	}
    90  	certPool := x509.NewCertPool()
    91  	certPool.AddCert(domain.Keys.Cert)
    92  	return domain, certPool, nil
    93  }
    94  
    95  func loadDomain() (*tao.Domain, *x509.CertPool, error) {
    96  	pwd := getPass()
    97  	domain, err := tao.LoadDomain(*configPath, pwd)
    98  	if domain == nil {
    99  		log.Printf("domainserver: no domain path - %s, pass - %s, err - %s\n",
   100  			*configPath, pwd, err)
   101  		return nil, nil, err
   102  	} else if err != nil {
   103  		log.Printf("domainserver: Couldn't load the config path %s: %s\n",
   104  			*configPath, err)
   105  		return nil, nil, err
   106  	}
   107  	log.Printf("domainserver: Loaded domain\n")
   108  	certPool := x509.NewCertPool()
   109  	certPool.AddCert(domain.Keys.Cert)
   110  	return domain, certPool, nil
   111  }
   112  
   113  func main() {
   114  	flag.Parse()
   115  	var domain *tao.Domain
   116  	var err error
   117  	if *createDomainFlag {
   118  		log.Println("Creating new domain...")
   119  		domain, _, err = createDomain()
   120  	} else {
   121  		log.Println("Loading domain info...")
   122  		domain, _, err = loadDomain()
   123  	}
   124  	text, err := ioutil.ReadFile(*trustedEntitiesPath)
   125  	if err != nil {
   126  		log.Fatalf("Can't open trusted entities file: %s", *trustedEntitiesPath)
   127  	}
   128  	trustedEntities := domain_service.TrustedEntities{}
   129  	err = proto.UnmarshalText(string(text), &trustedEntities)
   130  	if err != nil {
   131  		log.Fatalf("Can't parse trusted entities file: %s", *trustedEntitiesPath)
   132  	}
   133  	if err != nil {
   134  		log.Fatalln("domain_server: could not load domain:", err)
   135  	}
   136  	ln, err := net.Listen(*network, *addr)
   137  	if err != nil {
   138  		log.Fatalln("domain_server: could not listen at port:", err)
   139  	}
   140  	for {
   141  		conn, err := ln.Accept()
   142  		if err != nil {
   143  			log.Fatalln("domain_server: could not accept connection:", err)
   144  		}
   145  		// switch case
   146  		ms := util.NewMessageStream(conn)
   147  		var request domain_service.DomainServiceRequest
   148  		if err := ms.ReadMessage(&request); err != nil {
   149  			log.Printf("domain_server: Couldn't read request from channel: %s\n", err)
   150  			continue
   151  		}
   152  		switch *request.Type {
   153  		case domain_service.DomainServiceRequest_DOMAIN_CERT_REQUEST:
   154  			log.Println("Got Program cert request")
   155  			_, kPrin, prog, err := domain_service.VerifyAttestation(request.GetSerializedHostAttestation(),
   156  				domain)
   157  			if err != nil {
   158  				log.Printf("domain_server: Error verifying host att: %s\n", err)
   159  				sendError(err, ms)
   160  				continue
   161  			}
   162  			programKeyBytes := request.GetProgramKey()
   163  			verifier, err := tao.UnmarshalKey(programKeyBytes)
   164  			if err != nil {
   165  				log.Printf("domain_server: Error parsing program key: %v\n", err)
   166  				sendError(err, ms)
   167  				continue
   168  			}
   169  			if !verifier.ToPrincipal().Identical(kPrin) {
   170  				errStr := "domain_server: Program key in request does not match key being attested to."
   171  				log.Println(errStr)
   172  				sendError(errors.New(errStr), ms)
   173  				continue
   174  			}
   175  			prog_is_trusted := false
   176  			for _, trusted_prog := range trustedEntities.TrustedProgramTaoNames {
   177  				if trusted_prog == prog.String() {
   178  					prog_is_trusted = true
   179  				}
   180  			}
   181  			if !prog_is_trusted {
   182  				errStr := "domain_server: ProgramTaoName in request is not authorized to execute"
   183  				log.Println(errStr)
   184  				sendError(errors.New(errStr), ms)
   185  				continue
   186  			}
   187  			log.Println("domain_server: attestation passes verification checks, creating program cert")
   188  			cert, err := domain_service.GenerateProgramCert(domain, serialNumber, prog,
   189  				verifier, time.Now(), time.Now().AddDate(1, 0, 0))
   190  			if err != nil {
   191  				log.Printf("domain_server: Error generating program cert: %s\n", err)
   192  				sendError(err, ms)
   193  				continue
   194  			}
   195  			resp := &domain_service.DomainServiceResponse{
   196  				DerProgramCert: cert.Raw}
   197  			log.Println("domain_server: program cert created. Sending response back to program.")
   198  			if _, err := ms.WriteMessage(resp); err != nil {
   199  				log.Printf("domain_server: Error sending cert on the channel: %s\n ",
   200  					err)
   201  				continue
   202  			}
   203  		case domain_service.DomainServiceRequest_MANAGE_POLICY:
   204  			// TODO(sidtelang)
   205  		case domain_service.DomainServiceRequest_REVOKE_CERTIFICATE:
   206  			revokedCertificates, err = domain_service.RevokeCertificate(
   207  				request.GetSerializedPolicyAttestation(), revokedCertificates, domain)
   208  			if err != nil {
   209  				log.Printf("domain_server: Error revoking certificate: %s\n", err)
   210  			}
   211  			sendError(err, ms)
   212  		case domain_service.DomainServiceRequest_GET_CRL:
   213  			nowTime := time.Now()
   214  			expireTime := time.Now().AddDate(1, 0, 0)
   215  			crl, err := domain.Keys.SigningKey.CreateCRL(domain.Keys.Cert,
   216  				revokedCertificates, nowTime, expireTime)
   217  			resp := domain_service.DomainServiceResponse{}
   218  			if err != nil {
   219  				errStr := err.Error()
   220  				resp.ErrorMessage = &errStr
   221  			} else {
   222  				resp.Crl = crl
   223  			}
   224  			if _, err := ms.WriteMessage(&resp); err != nil {
   225  				log.Printf("domain_server: Error sending response on the channel: %s\n ", err)
   226  			}
   227  		}
   228  	}
   229  }
   230  
   231  func sendError(err error, ms *util.MessageStream) {
   232  	var errStr = ""
   233  	if err != nil {
   234  		errStr = err.Error()
   235  	}
   236  	resp := &domain_service.DomainServiceResponse{ErrorMessage: &errStr}
   237  	if _, err := ms.WriteMessage(resp); err != nil {
   238  		log.Printf("domain_server: Error sending resp on the channel: %s\n ", err)
   239  	}
   240  }