github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/go/apps/demo/demo_client/demo_client.go (about)

     1  // Copyright (c) 2014, Kevin Walsh.  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  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package main
    16  
    17  import (
    18  	"bufio"
    19  	"crypto/x509/pkix"
    20  	"flag"
    21  	"fmt"
    22  	"net"
    23  	"os"
    24  	"path"
    25  	"strings"
    26  
    27  	"github.com/jlmucb/cloudproxy/go/tao"
    28  	"github.com/jlmucb/cloudproxy/go/util/options"
    29  )
    30  
    31  var serverHost = flag.String("host", "localhost", "address for client/server")
    32  var serverPort = flag.String("port", "8123", "port for client/server")
    33  var serverAddr string // see main()
    34  var pingCount = flag.Int("n", 5, "Number of client/server pings")
    35  var demoAuth = flag.String("auth", "tao", "\"tcp\", \"tls\", or \"tao\"")
    36  var domainPathFlag = flag.String("tao_domain", "", "The Tao domain directory")
    37  var ca = flag.String("ca", "", "address for Tao CA, if any")
    38  
    39  var subprinRule = "(forall P: forall Hash: TrustedProgramHash(Hash) and Subprin(P, %v, Hash) implies Authorized(P, \"Execute\"))"
    40  
    41  func doRequest(guard tao.Guard, domain *tao.Domain, keys *tao.Keys) bool {
    42  	fmt.Printf("client: connecting to %s using %s authentication.\n", serverAddr, *demoAuth)
    43  	var conn net.Conn
    44  	var err error
    45  	network := "tcp"
    46  
    47  	switch *demoAuth {
    48  	case "tcp":
    49  		conn, err = net.Dial(network, serverAddr)
    50  	case "tls":
    51  		conn, err = tao.DialTLSWithKeys(network, serverAddr, keys)
    52  	case "tao":
    53  		conn, err = tao.Dial(network, serverAddr, guard, domain.Keys.VerifyingKey, keys)
    54  	}
    55  	if err != nil {
    56  		fmt.Fprintf(os.Stderr, "client: error connecting to %s: %s\n", serverAddr, err.Error())
    57  		return false
    58  	}
    59  	defer conn.Close()
    60  
    61  	_, err = fmt.Fprintf(conn, "Hello\n")
    62  	if err != nil {
    63  		fmt.Fprintf(os.Stderr, "client: can't write: %s\n", err.Error())
    64  		return false
    65  	}
    66  	msg, err := bufio.NewReader(conn).ReadString('\n')
    67  	if err != nil {
    68  		fmt.Fprintf(os.Stderr, "client: can't read: %s\n", err.Error())
    69  		return false
    70  	}
    71  	msg = strings.TrimSpace(msg)
    72  	fmt.Printf("client: got reply: %s\n", msg)
    73  	return true
    74  }
    75  
    76  func newTempCAGuard(v *tao.Verifier) (tao.Guard, error) {
    77  	g := tao.NewTemporaryDatalogGuard()
    78  	vprin := v.ToPrincipal()
    79  	rule := fmt.Sprintf(subprinRule, vprin)
    80  
    81  	if err := g.AddRule(rule); err != nil {
    82  		return nil, err
    83  	}
    84  
    85  	return g, nil
    86  }
    87  
    88  func doClient(domain *tao.Domain) {
    89  	network := "tcp"
    90  	keys, err := tao.NewTemporaryTaoDelegatedKeys(tao.Signing, tao.Parent())
    91  	options.FailIf(err, "client: couldn't generate temporary Tao keys")
    92  
    93  	// TODO(tmroeder): fix the name
    94  	pkInt := tao.PublicKeyAlgFromSignerAlg(*keys.SigningKey.Header.KeyType)
    95  	sigInt := tao.SignatureAlgFromSignerAlg(*keys.SigningKey.Header.KeyType)
    96  	cert, err := keys.SigningKey.CreateSelfSignedX509(pkInt, sigInt, int64(1),
    97  		&pkix.Name{
    98  			Organization: []string{"Google Tao Demo"}})
    99  	options.FailIf(err, "client: couldn't create a self-signed X.509 cert")
   100  
   101  	// TODO(kwalsh) keys should save cert on disk if keys are on disk
   102  	keys.Cert = cert
   103  
   104  	g := domain.Guard
   105  	if *ca != "" {
   106  		na, err := tao.RequestTruncatedAttestation(network, *ca, keys, domain.Keys.VerifyingKey)
   107  		options.FailIf(err, "client: couldn't get a truncated attestation from %s: %s\n", *ca)
   108  
   109  		keys.Delegation = na
   110  
   111  		// If we're using a CA, then use a custom guard that accepts only
   112  		// programs that have talked to the CA.
   113  		g, err = newTempCAGuard(domain.Keys.VerifyingKey)
   114  		options.FailIf(err, "client: couldn't set up a new guard")
   115  	}
   116  
   117  	pingGood := 0
   118  	pingFail := 0
   119  	for i := 0; i < *pingCount || *pingCount < 0; i++ { // negative means forever
   120  		if doRequest(g, domain, keys) {
   121  			pingGood++
   122  		} else {
   123  			pingFail++
   124  		}
   125  		fmt.Printf("client: made %d connections, finished %d ok, %d bad pings\n", i+1, pingGood, pingFail)
   126  	}
   127  }
   128  
   129  func main() {
   130  	flag.Parse()
   131  
   132  	// Check to see if we are running in Docker mode with linked containers.
   133  	// If so, then there will be an environment variable SERVER_PORT that
   134  	// will contain a value of the form tcp://<ip>:<port>
   135  	serverEnvVar := os.Getenv("SERVER_PORT")
   136  	if serverEnvVar == "" {
   137  		serverAddr = net.JoinHostPort(*serverHost, *serverPort)
   138  	} else {
   139  		serverAddr = strings.TrimPrefix(serverEnvVar, "tcp://")
   140  		if serverAddr == serverEnvVar {
   141  			options.Usage("client: invalid SERVER_PORT environment variable value '%s'\n", serverEnvVar)
   142  		}
   143  	}
   144  
   145  	switch *demoAuth {
   146  	case "tcp", "tls", "tao":
   147  	default:
   148  		options.Usage("unrecognized authentication mode: %s\n", *demoAuth)
   149  	}
   150  
   151  	fmt.Println("Go Tao Demo Client")
   152  
   153  	if tao.Parent() == nil {
   154  		options.Fail(nil, "can't continue: No host Tao available")
   155  	}
   156  
   157  	domain, err := tao.LoadDomain(configPath(), nil)
   158  	options.FailIf(err, "error: couldn't load the tao domain from %s\n", configPath())
   159  
   160  	doClient(domain)
   161  	fmt.Println("Client Done")
   162  }
   163  
   164  func domainPath() string {
   165  	if *domainPathFlag != "" {
   166  		return *domainPathFlag
   167  	}
   168  	if path := os.Getenv("TAO_DOMAIN"); path != "" {
   169  		return path
   170  	}
   171  	options.Usage("Must supply -tao_domain or set $TAO_DOMAIN")
   172  	return ""
   173  }
   174  
   175  func configPath() string {
   176  	return path.Join(domainPath(), "tao.config")
   177  }