 +}
 diff --git a/apps/fileproxy/fileproxymessages.proto b/apps/fileproxy/fileproxymessages.proto
 new file mode 100644
-index 0000000..ba0aaa6
+index 0000000..be1c6ab
 --- /dev/null
 +++ b/apps/fileproxy/fileproxymessages.proto
-@@ -0,0 +1,52 @@
+@@ -0,0 +1,59 @@
 +//  Copyright (c) 2013, Google Inc.  All rights reserved.
 +//
 +// Licensed under the Apache License, Version 2.0 (the "License");

+#
+PROG_DIR=/Users/manferdelli/src/github.com/jlmucb/cloudproxy/apps/fileproxy/keynegoserver
+linux_host -path="../hostdomain/linux_tao_host" -run -- $PROG_DIR/keynegoserver 
diff --git a/apps/fileproxy/keynegoserver/keynegoserver.go b/apps/fileproxy/keynegoserver/keynegoserver.go
new file mode 100644
index 0000000..cf282b2
--- /dev/null
+++ b/apps/fileproxy/keynegoserver/keynegoserver.go
@@ -0,0 +1,276 @@
+// Copyright (c) 2014, Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//     http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+	"crypto/tls"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"flag"
+	"fmt"
+	"os"
+	"net"
+	"errors"
+	"time"
+	"io/ioutil"
+	"crypto/rand"
+	"math/big"
+	"code.google.com/p/goprotobuf/proto"
+	"github.com/jlmucb/cloudproxy/tao"
+	taonet "github.com/jlmucb/cloudproxy/tao/net"
+	"github.com/jlmucb/cloudproxy/tao/auth"
+	"github.com/jlmucb/cloudproxy/util"
+)
+
+var network = flag.String("network", "tcp", "The network to use for connections")
+var addr = flag.String("addr", "localhost:8124", "The address to listen on")
+var domainPass = flag.String("password", "nopassword", "The domain password for the policy key")
+var configPath = flag.String("config", "tao.config", "The Tao domain config")
+
+var	SerialNumber int64
+
+// return is terminate, error
+func KeyNegoRequest(conn net.Conn, policyKey *tao.Keys,guard tao.Guard) (bool, error){
+	fmt.Printf("keynegoerver: KeyNegoRequest\n")
+	// Expect an attestation from the client.
+	ms := util.NewMessageStream(conn)
+	var a tao.Attestation
+	if err := ms.ReadMessage(&a); err != nil {
+		fmt.Fprintln(os.Stderr, "Couldn't read attestation from channel:", err)
+		return false, err
+	}
+
+	peerCert := conn.(*tls.Conn).ConnectionState().PeerCertificates[0]
+	if err := taonet.ValidatePeerAttestation(&a, peerCert, guard); err != nil {
+		fmt.Fprintln(os.Stderr, "Couldn't validate peer attestation:", err)
+		return false, err
+	}
+
+	// sign cert and put it in attestation statement
+	// a consists of serialized statement, sig and SignerInfo
+	// a is a says speaksfor, Delegate of speaksfor is cert and should be DER encoded
+
+	// get underlying says
+	fmt.Print("keynegoserver, attest: ",  a)
+	fmt.Print("\n")
+	f, err := auth.UnmarshalForm(a.SerializedStatement)
+	if err != nil {
+		fmt.Printf("\nkeynegoserver: cant unmarshal a.SerializedStatement\n")
+		return false, err
+	}
+	fmt.Print("\nkeynegoserver, unmarshaled serialized: ",  f.String())
+	fmt.Print("\n")
+
+	var saysStatement *auth.Says
+	if ptr, ok := f.(*auth.Says); ok {
+		saysStatement = ptr
+	} else if val, ok := f.(auth.Says); ok {
+		saysStatement = &val
+	}
+	sf, ok := saysStatement.Message.(auth.Speaksfor)
+	if(ok!=true) {
+		fmt.Printf("keynegoserver: says doesnt have speaksfor message\n")
+		return false, err
+	}
+	fmt.Print("keynegoserver, speaksfor: ",  sf)
+	fmt.Print("\n")
+	kprin, ok := sf.Delegate.(auth.Prin)
+	if(ok!=true) {
+		fmt.Printf("keynegoserver: speaksfor Delegate is not auth.Prin\n")
+		return false, err
+	}
+	subjectPrin, ok:= sf.Delegator.(auth.Prin)
+	if(ok!=true ) {
+		fmt.Printf("keynegoserver: cant get subject principal\n")
+		return false,errors.New("Cant get principal name from verifier") 
+	}
+	subjectnamestr:= subjectPrin.String()
+	fmt.Printf("keynegoserver: subject principal name: %s\n", subjectnamestr)
+	details:= tao.X509Details {
+		Country: "US",
+		Organization: "Google",
+		OrganizationalUnit: subjectnamestr,
+		CommonName: "localhost", }
+	subjectname:= tao.NewX509Name(details)
+	SerialNumber= SerialNumber+1
+	template := &x509.Certificate{
+		SignatureAlgorithm: x509.ECDSAWithSHA256,
+		PublicKeyAlgorithm: x509.ECDSA,
+		Version:            2, // x509v3
+		// It's always allowed for self-signed certs to have serial 1.
+		SerialNumber: new(big.Int).SetInt64(SerialNumber),
+		Subject:      *subjectname,
+		NotBefore:    time.Now(),
+		NotAfter:     time.Now().AddDate(1 /* years */, 0 /* months */, 0 /* days */),
+		KeyUsage:    x509.KeyUsageKeyAgreement,
+		ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
+		}
+	verifier,err:= tao.FromPrincipal(kprin)
+	if(err!=nil) {
+		return false, errors.New("cant get principal from kprin")
+	}
+	clientDerCert, err := x509.CreateCertificate(rand.Reader, template, policyKey.Cert, 
+					verifier.GetVerifierEc(),
+	                                policyKey.SigningKey.GetSignerEc())
+	if(err!=nil) {
+		fmt.Printf("keynegoserver: cant create client certificate: %s\n", err)
+		return false, err
+	}
+	err= ioutil.WriteFile("ClientCert", clientDerCert, os.ModePerm)
+
+	nowTime:= time.Now().UnixNano()
+	expireTime:= time.Now().AddDate(1, 0, 0).UnixNano()
+	// replace self signed cert in attest request
+	newspeaksFor:= &auth.Speaksfor{
+		Delegate:   auth.Bytes(clientDerCert),
+		Delegator:  sf.Delegator,}
+	keynegoSays:= &auth.Says{
+		Speaker:  policyKey.SigningKey.ToPrincipal(),
+		Time: &nowTime,
+		Expiration: &expireTime,
+		Message: newspeaksFor,}
+
+	delegator, ok := sf.Delegator.(auth.Prin)
+	if !ok {
+		fmt.Printf("keynegoserver: the delegator must be a principal")
+		return false, err
+	}
+	var prog auth.PrinExt
+	found := false
+	for _, sprin := range delegator.Ext {

+echo "rebuilding keynegoserver"
+go build keynegoserver.go
+echo "done"
diff --git a/apps/fileproxy/rollbackhandler.go b/apps/fileproxy/rollbackhandler.go
new file mode 100644
index 0000000..bb47b1d
--- /dev/null
+++ b/apps/fileproxy/rollbackhandler.go
@@ -0,0 +1,338 @@
+// Copyright (c) 2014, Google Corporation.  All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//     http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// File: rollbackhandler.go
+
+package fileproxy
+
+import (
+	"crypto/sha256"
+	"encoding/binary"
+	"errors"
+	"log"
+
+	"code.google.com/p/goprotobuf/proto"
+
+	"github.com/jlmucb/cloudproxy/util"
+)
+
+type NameandHash struct {
+	ItemName string
+	Hash     []byte
+}
+
+type RollbackProgramInfo struct {
+	MasterInfoSaveFile string
+	HashSaveFile       string
+	ProgramName        string
+	MonotonicCounter   int64
+	Initialized        bool
+	NameandHashArray   []NameandHash
+}
+
+type RollbackMaster struct {
+	ProgramName string
+	Initialized bool
+	ProgramInfo []RollbackProgramInfo
+}
+
+func (r *RollbackMaster) FindRollbackProgramTable(programName string) *RollbackProgramInfo {
+	for i := range r.ProgramInfo {
+		if r.ProgramInfo[i].ProgramName == programName {
+			return &r.ProgramInfo[i]
+		}
+	}
+	return nil
+}
+
+func (r *RollbackMaster) AddRollbackProgramTable(programName string) *RollbackProgramInfo {
+	log.Printf("AddRollbackProgramTable: %s\n", programName)
+	pi := r.FindRollbackProgramTable(programName)
+	if pi != nil {
+		return pi
+	}
+	if len(r.ProgramInfo) >= cap(r.ProgramInfo) {
+		t := make([]RollbackProgramInfo, 2*cap(r.ProgramInfo))
+		copy(t, r.ProgramInfo)
+		r.ProgramInfo = t
+	}
+	r.ProgramInfo = r.ProgramInfo[0 : len(r.ProgramInfo)+1]
+	log.Printf("len(r.ProgramInfo)= %d, cap(r.ProgramInfo)= %d\n", len(r.ProgramInfo), cap(r.ProgramInfo))
+	pi = &r.ProgramInfo[len(r.ProgramInfo)-1]
+	pi.ProgramName = programName
+	pi.MonotonicCounter = 3
+	pi.NameandHashArray = make([]NameandHash, 100)
+	pi.NameandHashArray = pi.NameandHashArray[0:0]
+	log.Printf("len(pi.pi.NameandHashArray)= %d, cap(pi.pi.NameandHashArray)= %d\n", len(pi.NameandHashArray), cap(pi.NameandHashArray))
+	pi.Initialized = true
+	return pi
+}
+
+func (r *RollbackMaster) ReadMasterRollbackInfo(masterFile string, hashFile string) bool {
+	return false
+}
+
+func (r *RollbackMaster) SaveMasterRollbackInfo(masterFile string, hashFile string) bool {
+	return false
+}
+
+func (pi *RollbackProgramInfo) ReadProgramRollbackInfo(programName string, masterFile string, hashFile string) bool {
+	return false
+}
+
+func (pi *RollbackProgramInfo) SaveProgramRollbackInfo(programName string, masterFile string, hashFile string) bool {
+	return false
+}
+
+func (pi *RollbackProgramInfo) FindRollbackHashEntry(itemName string) *NameandHash {
+	for i := range pi.NameandHashArray {
+		log.Printf("FindRollbackHashEntry %s %s\n", itemName, pi.NameandHashArray[i].ItemName)
+		if pi.NameandHashArray[i].ItemName == itemName {
+			return &pi.NameandHashArray[i]
+		}
+	}
+	return nil
+}
+
+func (pi *RollbackProgramInfo) AddHashEntry(itemName string, hash []byte) *NameandHash {
+	log.Printf("AddHashEntry %s\n", itemName)
+	he := pi.FindRollbackHashEntry(itemName)
+	if he != nil {
+		he.Hash = hash
+		return he
+	}
+	if len(pi.NameandHashArray) >= cap(pi.NameandHashArray) {
+		t := make([]NameandHash, 2*cap(pi.NameandHashArray))
+		copy(t, pi.NameandHashArray)
+		pi.NameandHashArray = t
+	}
+	pi.NameandHashArray = pi.NameandHashArray[0 : len(pi.NameandHashArray)+1]
+	he = &pi.NameandHashArray[len(pi.NameandHashArray)-1]
+	he.ItemName = itemName
+	he.Hash = hash
+	log.Printf("item: %s, hash %x\n", itemName, hash)
+	return he
+}
+
+func (r *RollbackMaster) InitRollbackMaster(masterprogramName string) bool {
+	log.Printf("InitRollbackMaster\n")
+	r.Initialized = true
+	r.ProgramName = masterprogramName
+	r.ProgramInfo = make([]RollbackProgramInfo, 100)
+	r.ProgramInfo = r.ProgramInfo[0:0]
+	log.Printf("len(r.ProgramInfo)= %d, cap(r.ProgramInfo)= %d\n", len(r.ProgramInfo), cap(r.ProgramInfo))
+	// read master
+	// decrypt
+	// update
+
+	// read hash table
+	// decrypt
+	// update
+	return true
+}
+
+func (r *RollbackMaster) SetRollbackCounter(ms *util.MessageStream, programName string, counter int64) bool {
+	pi := r.FindRollbackProgramTable(programName)
+	if pi == nil {
+		log.Printf("SetRollbackCounter: program has no program info table 1")
+		SendResponse(ms, "failed", "Rollback doesn't exist", 0)
+		return false
+	}
+	if pi.MonotonicCounter > counter {
+		log.Printf("SetRollbackCounter: can't set counter backwards")
+		SendResponse(ms, "failed", "Rollback counter can't decrease", 0)
+		return false
+	}
+	pi.MonotonicCounter = counter
+	log.Printf("SetRollbackCounter (%s) table counter: %d\n", pi.ProgramName, pi.MonotonicCounter)
+	SendResponse(ms, "succeeded", "", 0)
+	return true
+}
+
+func (r *RollbackMaster) SetRollbackResourceHash(ms *util.MessageStream, programName string, itemName string) bool {
+	pi := r.FindRollbackProgramTable(programName)
+	if pi == nil {
+		log.Printf("SetRollbackResourceHash: program has no program info table 2")
+		SendResponse(ms, "failed", "Rollback doesn't exist", 0)
+		return false
+	}
+	SendResponse(ms, "succeeded", "", 0)
+	// get hash
+	hash, err := GetProtocolMessage(ms)
+	if err != nil {
+		log.Printf("SetRollbackResourceHash: GetProtocolMessage failed\n")
+		SendResponse(ms, "failed", "Rollback doesn't exist", 0)
+		return false
+	}
+	hi := pi.FindRollbackHashEntry(itemName)
+	if hi == nil {
+		hi = pi.AddHashEntry(itemName, hash)
+		if hi == nil {
+			log.Printf("SetRollbackResourceHash: no hash entry\n")
+			SendResponse(ms, "failed", "can't insert entry", 0)
+			return false
+		}
+	} else {
+		log.Printf("SetRollbackResourceHash, found %s entry\n", hi.ItemName)
+		hi.Hash = hash
+	}
+	return true
+}
+
+func (r *RollbackMaster) GetRollbackCounter(ms *util.MessageStream, programName string) bool {
+	pi := r.FindRollbackProgramTable(programName)
+	if pi == nil {
+		log.Printf("GetRollbackCounter: program has no program info table\n")
+		SendResponse(ms, "failed", "Rollback doesn't exist", 0)
+		return false
+	}
+	log.Printf("GetRollbackCounter(%s), counter: %d\n", pi.ProgramName, pi.MonotonicCounter)
+	SendCounterResponse(ms, "succeeded", "", pi.MonotonicCounter)
+	return true
+}
+
+func (r *RollbackMaster) GetRollbackHashedVerifier(ms *util.MessageStream, programName string, itemName string) bool {
+	log.Printf("GetRollbackHashedVerifier\n")
+	pi := r.FindRollbackProgramTable(programName)
+	if pi == nil {
+		log.Printf("GetRollbackHashedVerifier: program has no program info table")
+		SendResponse(ms, "failed", "Rollback doesn't exist", 0)
+		return false
+	}
+	hi := pi.FindRollbackHashEntry(itemName)
+	if hi == nil {
+		log.Printf("GetRollbackResourceHash: program has no hash entry for %s\n", itemName)
+		SendResponse(ms, "failed", "can't insert entry", 0)
+		return false
+	}
+	// now has the epoch and the hash and return thatkk
+	sha256Hash := sha256.New()
+	b := make([]byte, 8)
+	binary.PutVarint(b, pi.MonotonicCounter)
+	sha256Hash.Write(b)
+	sha256Hash.Write(hi.Hash)
+	sha256Hash.Write(b)
+	hash := sha256Hash.Sum(nil)
+	SendResponse(ms, "succeeded", "", 0)
+	SendProtocolMessage(ms, len(hash), hash)
+	return true
+}
+
+// Update hash for resouce named resource
+func ClientSetRollbackCounter(ms *util.MessageStream, counter int64) bool {
+	SendCounterRequest(ms, counter)
+	status, _, _, err := GetResponse(ms)
+	if err != nil || status == nil || *status != "succeeded" {
+		return false
+	}
+	return true
+}
+
+func ClientSetResourceHashRequest(ms *util.MessageStream, clientProgramName string, item string, hash []byte) bool {
+	log.Printf("ClientSetResourceHashRequest %s, %s\n", clientProgramName, item)
+	action := "setrollbackhash"
+	SendRequest(ms, nil, &action, &item, nil)
+	status, _, _, err := GetResponse(ms)
+	if err != nil || status == nil || *status != "succeeded" {
+		log.Printf("ClientSetResourceHashRequest failed\n")
+		return false
+	}
+	err = SendProtocolMessage(ms, len(hash), hash)
+	return true
+}
+
+func ClientGetRollbackCounter(ms *util.MessageStream, clientProgramName string) (bool, int64) {
+	log.Printf("ClientGetRollbackCounter%s, %s\n", clientProgramName)
+	action := "getrollbackcounter"
+	SendRequest(ms, &clientProgramName, &action, nil, nil)
+	status, _, counter, err := GetCounterResponse(ms)
+	if err != nil || status == nil || *status != "succeeded" || counter == nil {
+		if err != nil {
+			log.Printf("ClientGetRollbackCounter, err is not nil\n")
+		}
+		if status == nil {
+			log.Printf("ClientGetRollbackCounter, status is nil\n")
+		}
+		log.Printf("ClientGetRollbackCounter: %s\n", *status)
+		if counter == nil {
+			log.Printf("ClientGetRollbackCounter, counter is nil\n")
+		}
+		return false, 0
+	}
+	return true, *counter
+}
+
+func ClientGetRollbackHashedVerifierRequest(ms *util.MessageStream, clientProgramName string, item string) (bool, []byte) {
+	log.Printf("ClientGetRollbackHashedVerifierRequest: %s, %s\n", clientProgramName, item)
+	action := "getrollbackcounterverifier"
+	SendRequest(ms, nil, &action, &item, nil)
+	status, _, _, err := GetResponse(ms)
+	if status == nil || *status != "succeeded" || err != nil {
+		return false, nil
+	}
+	hash, err := GetProtocolMessage(ms)
+	return true, hash
+}
+
+// First return value is terminate flag
+func (r *RollbackMaster) HandleServiceRequest(ms *util.MessageStream, programPolicyObject *ProgramPolicy, clientProgramName string, request []byte) (bool, error) {
+	log.Printf("rollbackhandler: HandleServiceRequest for %s\n", clientProgramName)
+
+	fpMessage := new(FPMessage)
+	err := proto.Unmarshal(request, fpMessage)
+	if err != nil {
+		return false, errors.New("HandleService can't unmarshal request")
+	}
+	if fpMessage.MessageType == nil {
+		return false, errors.New("HandleService: no message type")
+	}
+	switch MessageType(*fpMessage.MessageType) {
+	case MessageType_REQUEST:
+	default:
+		return false, errors.New("HandleService does not get MessageType_REQUEST")
+	}
+	action := fpMessage.ActionName
+	if action == nil {
+		SendResponse(ms, "failed", "", 0)
+		return false, errors.New("no action")
+	}
+
+	switch *action {
+	case "setrollbackcounter":
+		if fpMessage.MonotonicCounter == nil {
+			log.Printf("HandleServiceRequest: no counter in setrollbackcounter message")
+			SendResponse(ms, "failed", "no counter", 0)
+		}
+		_ = r.SetRollbackCounter(ms, clientProgramName, *fpMessage.MonotonicCounter)
+		return false, nil
+	case "getrollbackcounter":
+		_ = r.GetRollbackCounter(ms, clientProgramName)
+		return false, nil
+	case "setrollbackhash":
+		if fpMessage.ResourceName == nil {
+			log.Printf("HandleServiceRequest: no resource name in setrollbackhash message")
+			SendResponse(ms, "failed", "no counter", 0)
+		}
+		_ = r.SetRollbackResourceHash(ms, clientProgramName, *fpMessage.ResourceName)
+		return false, nil
+	case "getrollbackcounterverifier":
+		if fpMessage.ResourceName == nil {
+			log.Printf("HandleServiceRequest: no resource name in getrollbackcounterverifier message")
+			SendResponse(ms, "failed", "no counter", 0)
+		}
+		r.GetRollbackHashedVerifier(ms, clientProgramName, *fpMessage.ResourceName)
+		return false, nil
+	default:
+		SendResponse(ms, "failed", "", 0)
+		return false, errors.New("unsupported action")
+	}
+}
diff --git a/apps/fileproxy/rollbackserver/rebuild b/apps/fileproxy/rollbackserver/rebuild
new file mode 100755
index 0000000..928d2a7
--- /dev/null
+++ b/apps/fileproxy/rollbackserver/rebuild
@@ -0,0 +1,8 @@
+#
+echo "rebuilding rollbackproxy"
+cd ..
+go build ...
+cd rollbackserver
+echo "rebuilding rollbackserver"
+go build rollbackserver.go
+echo "done"
diff --git a/apps/fileproxy/rollbackserver/rollbackserver.go b/apps/fileproxy/rollbackserver/rollbackserver.go
new file mode 100644
index 0000000..70deb11
--- /dev/null
+++ b/apps/fileproxy/rollbackserver/rollbackserver.go
@@ -0,0 +1,238 @@
+// Copyright (c) 2014, Google Corporation.  All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//     http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// File: rollbackserver.go
+
+package main
+
+import (
+	"crypto/sha256"
+	"crypto/tls"
+	"crypto/x509"
+	"encoding/hex"
+	"flag"
+	"log"
+	"net"
+
+	"github.com/jlmucb/cloudproxy/apps/fileproxy"
+	tao "github.com/jlmucb/cloudproxy/tao"
+	"github.com/jlmucb/cloudproxy/tao/auth"
+	taonet "github.com/jlmucb/cloudproxy/tao/net"
+	"github.com/jlmucb/cloudproxy/util"
+)
+
+var hostcfg = flag.String("../hostdomain/tao.config", "../hostdomain/tao.config", "path to host tao configuration")
+var serverHost = flag.String("host", "localhost", "address for client/server")
+var serverPort = flag.String("port", "8129", "port for client/server")
+var rollbackserverPath = flag.String("rollbackserver_files/", "rollbackserver_files/", "rollbackserver directory")
+var serverAddr string
+
+var DerPolicyCert []byte
+var SigningKey tao.Keys
+var SymKeys []byte
+var ProgramCert []byte
+
+func clientServiceThead(ms *util.MessageStream, clientName string, rollbackPolicy *fileproxy.ProgramPolicy, rollbackMasterTable *fileproxy.RollbackMaster) {
+	log.Printf("rollbackserver: clientServiceThead\n")
+	pi := rollbackMasterTable.AddRollbackProgramTable(clientName)
+	if pi == nil {
+		log.Printf("rollbackserver cannot rollbackMasterTable.AddRollbackProgramTable\n")
+		return
+	}
+	// How do I know if the connection terminates?
+	for {
+		log.Printf("clientServiceThead: ReadString\n")
+		strbytes, err := ms.ReadString()
+		if err != nil {
+			return
+		}
+		terminate, err := rollbackMasterTable.HandleServiceRequest(ms, rollbackPolicy, clientName, []byte(strbytes))
+		if terminate {
+			break
+		}
+	}
+	log.Printf("fileserver: client thread terminating\n")
+}
+
+func server(serverAddr string, prin string, rollbackPolicy *fileproxy.ProgramPolicy, rollbackMasterTable *fileproxy.RollbackMaster) {
+	var sock net.Listener
+	log.Printf("fileserver: server\n")
+
+	policyCert, err := x509.ParseCertificate(DerPolicyCert)
+	if err != nil {
+		log.Printf("fileserver: can't ParseCertificate\n")
+		return
+	}
+	pool := x509.NewCertPool()
+	pool.AddCert(policyCert)
+	tlsc, err := taonet.EncodeTLSCert(&SigningKey)
+	if err != nil {
+		log.Printf("fileserver, encode error: ", err)
+		log.Printf("\n")
+		return
+	}
+	conf := &tls.Config{
+		RootCAs:            pool,
+		Certificates:       []tls.Certificate{*tlsc},
+		InsecureSkipVerify: false,
+		ClientAuth:         tls.RequireAnyClientCert,
+	}
+	log.Printf("Listenting\n")
+	sock, err = tls.Listen("tcp", serverAddr, conf)
+	if err != nil {
+		log.Printf("rollbackserver, listen error: ", err)
+		log.Printf("\n")
+		return
+	}
+	for {
+		log.Printf("rollbackserver: at Accept\n")
+		conn, err := sock.Accept()
+		if err != nil {
+			log.Printf("rollbackserver: can't accept connection: %s\n", err.Error())
+		}
+		var clientName string
+		clientName = "XYZZY"
+		err = conn.(*tls.Conn).Handshake()
+		if err != nil {
+			log.Printf("TLS handshake failed\n")
+		}
+		peerCerts := conn.(*tls.Conn).ConnectionState().PeerCertificates
+		if peerCerts == nil {
+			log.Printf("rollbackserver: can't get peer list\n")
+		} else {
+			peerCert := conn.(*tls.Conn).ConnectionState().PeerCertificates[0]
+			if peerCert.Raw == nil {
+				log.Printf("rollbackserver: can't get peer name\n")
+			} else {
+				if peerCert.Subject.OrganizationalUnit != nil {
+					clientName = peerCert.Subject.OrganizationalUnit[0]
+				}
+			}
+		}
+		log.Printf("rollbackserver, peer name: %s\n", clientName)
+		ms := util.NewMessageStream(conn)
+		go clientServiceThead(ms, clientName, rollbackPolicy, rollbackMasterTable)
+	}
+}
+
+func main() {
+	log.Printf("rollback server\n")
+
+	var rollbackMaster fileproxy.RollbackMaster
+	var RollbackMaster *fileproxy.RollbackMaster
+	var rollbackProgramPolicyObject fileproxy.ProgramPolicy
+	var RollbackProgramPolicyObject *fileproxy.ProgramPolicy
+	RollbackMaster = &rollbackMaster
+	RollbackProgramPolicyObject = &rollbackProgramPolicyObject
+
+	flag.Parse()
+	serverAddr = *serverHost + ":" + *serverPort
+
+	hostDomain, err := tao.LoadDomain(*hostcfg, nil)
+	if err != nil {
+		return
+	}
+	log.Printf("rollbackserver: Domain name: %s\n", hostDomain.ConfigPath)
+	DerPolicyCert = nil
+	if hostDomain.Keys.Cert != nil {
+		DerPolicyCert = hostDomain.Keys.Cert.Raw
+	}
+	if DerPolicyCert == nil {
+		log.Printf("rollbackserver: can't retrieve policy cert\n")
+		return
+	}
+
+	/*
+	 Replace with: hostDomai.ExtendTaoDomain(tao)
+	*/
+	sha256Hash := sha256.New()
+	sha256Hash.Write(DerPolicyCert)
+	policyCertHash := sha256Hash.Sum(nil)
+	hexCertHash := hex.EncodeToString(policyCertHash)
+	e := auth.PrinExt{Name: hexCertHash}
+	err = tao.Parent().ExtendTaoName(auth.SubPrin{e})
+	if err != nil {
+		return
+	}
+
+	e = auth.PrinExt{Name: "rollbackserver_version_1"}
+	err = tao.Parent().ExtendTaoName(auth.SubPrin{e})
+	if err != nil {
+		log.Printf("rollbackserver: can't get tao name\n")
+		return
+	}
+
+	taoName, err := tao.Parent().GetTaoName()
+	if err != nil {
+		return
+	}
+	log.Printf("rollbackserver: my name is %s\n", taoName)
+
+	sealedSymmetricKey, sealedSigningKey, derCert, delegation, err := fileproxy.LoadProgramKeys(*rollbackserverPath)
+	if err != nil {
+		log.Printf("rollbackserver: can't retrieve key material\n")
+	}
+	if sealedSymmetricKey == nil || sealedSigningKey == nil || delegation == nil || derCert == nil {
+		log.Printf("rollbackserver: No key material present\n")
+	}
+	ProgramCert = derCert
+
+	defer fileproxy.ZeroBytes(SymKeys)
+	if sealedSymmetricKey != nil {
+		symkeys, policy, err := tao.Parent().Unseal(sealedSymmetricKey)
+		if err != nil {
+			return
+		}
+		if policy != tao.SealPolicyDefault {
+			log.Printf("rollbackserver: unexpected policy on unseal\n")
+		}
+		SymKeys = symkeys
+		log.Printf("rollbackserver: Unsealed symKeys: % x\n", SymKeys)
+	} else {
+		symkeys, err := fileproxy.InitializeSealedSymmetricKeys(*rollbackserverPath, tao.Parent(), fileproxy.SizeofSymmetricKeys)
+		if err != nil {
+			log.Printf("rollbackserver: InitializeSealedSymmetricKeys error: %s\n", err)
+		}
+		SymKeys = symkeys
+		log.Printf("rollbackserver: InitilizedsymKeys: % x\n", SymKeys)
+	}
+
+	if sealedSigningKey != nil {
+		log.Printf("rollbackserver: retrieving signing key\n")
+		signingkey, err := fileproxy.SigningKeyFromBlob(tao.Parent(),
+			sealedSigningKey, derCert, delegation)
+		if err != nil {
+			log.Printf("rollbackserver: SigningKeyFromBlob error: %s\n", err)
+		}
+		SigningKey = *signingkey
+		log.Printf("rollbackserver: Retrieved Signing key: % x\n", SigningKey)
+	} else {
+		log.Printf("rollbackserver: initializing signing key\n")
+		signingkey, err := fileproxy.InitializeSealedSigningKey(*rollbackserverPath,
+			tao.Parent(), *hostDomain)
+		if err != nil {
+			log.Printf("rollbackserver: InitializeSealedSigningKey error: %s\n", err)
+		}
+		SigningKey = *signingkey
+		log.Printf("rollbackserver: Initialized signingKey\n")
+		ProgramCert = SigningKey.Cert.Raw
+	}
+	taoNameStr := taoName.String()
+	_ = RollbackProgramPolicyObject.InitProgramPolicy(DerPolicyCert, taoNameStr, SigningKey, SymKeys, ProgramCert)
+	RollbackMaster.InitRollbackMaster(taoNameStr)
+
+	server(serverAddr, taoNameStr, RollbackProgramPolicyObject, RollbackMaster)
+	if err != nil {
+		log.Printf("rollbackserver: server error\n")
+	}
+	log.Printf("rollbackserver: done\n")
+}
diff --git a/apps/tao_admin/main.go b/apps/tao_admin/main.go
index 7c89844..96eb492 100644
--- a/apps/tao_admin/main.go
