github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/go/apps/newfileproxy/resourcemanager/resources.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  // File: resources.go
    14  
    15  package resourcemanager
    16  
    17  import (
    18  	"fmt"
    19  	"io/ioutil"
    20  	"path"
    21  	"sync"
    22  	"time"
    23  
    24  	"github.com/golang/protobuf/proto"
    25  	"github.com/jlmucb/cloudproxy/go/tao"
    26  )
    27  
    28  func EncodeTime(t time.Time) (string, error) {
    29  	const longForm = "2006-01-02T15:04:05.999999999Z07:00"
    30  	return t.Format(longForm), nil
    31  }
    32  
    33  func DecodeTime(s string) (*time.Time, error) {
    34  	const longForm = "2006-01-02T15:04:05.999999999Z07:00"
    35  	tt, err := time.Parse(longForm, s)
    36  	if err != nil {
    37  		return nil, err
    38  	}
    39  	return &tt, nil
    40  }
    41  
    42  // MakeCombinedPrincipalFromOne
    43  func MakeCombinedPrincipalFromOne(appPrincipal *PrincipalInfo) *CombinedPrincipal {
    44  	cp := new(CombinedPrincipal)
    45  	cp.Principals = append(cp.Principals, appPrincipal)
    46  	return cp
    47  }
    48  
    49  // MakeCombinedPrincipalFromTwo
    50  func MakeCombinedPrincipalFromTwo(appPrincipal *PrincipalInfo, userPrincipal *PrincipalInfo) *CombinedPrincipal {
    51  	cp := new(CombinedPrincipal)
    52  	cp.Principals = append(cp.Principals, appPrincipal)
    53  	cp.Principals = append(cp.Principals, userPrincipal)
    54  	return cp
    55  }
    56  
    57  func SameCombinedPrincipal(p1 CombinedPrincipal, p2 CombinedPrincipal) bool {
    58  	if len(p1.Principals) != len(p2.Principals) {
    59  		return false
    60  	}
    61  	for i := 0; i < len(p1.Principals); i++ {
    62  		if *p1.Principals[i].Name != *p2.Principals[i].Name {
    63  			return false
    64  		}
    65  	}
    66  	return true
    67  }
    68  
    69  // Add Owner
    70  func (info *ResourceInfo) AddOwner(p CombinedPrincipal, mutex *sync.RWMutex) error {
    71  	if mutex != nil {
    72  		mutex.Lock()
    73  		defer mutex.Unlock()
    74  	}
    75  	info.Owners = append(info.Owners, &p)
    76  	return nil
    77  }
    78  
    79  // Add Reader
    80  func (info *ResourceInfo) AddReader(p CombinedPrincipal, mutex *sync.RWMutex) error {
    81  	if mutex != nil {
    82  		mutex.Lock()
    83  		defer mutex.Unlock()
    84  	}
    85  	info.Readers = append(info.Readers, &p)
    86  	return nil
    87  }
    88  
    89  // Add Writer
    90  func (info *ResourceInfo) AddWriter(p CombinedPrincipal, mutex *sync.RWMutex) error {
    91  	if mutex != nil {
    92  		mutex.Lock()
    93  		defer mutex.Unlock()
    94  	}
    95  	info.Writers = append(info.Writers, &p)
    96  	return nil
    97  }
    98  
    99  // FindCombinedPrincipalPosition looks up the resource by its name and returns position in stack.
   100  func FindCombinedPrincipalPosition(toFind CombinedPrincipal, cpList []*CombinedPrincipal) int {
   101  	// No mutex is needed since enclosing function should lock.
   102  	for i := 0; i < len(cpList); i++ {
   103  		if SameCombinedPrincipal(toFind, *cpList[i]) {
   104  			return i
   105  		}
   106  	}
   107  	return -1
   108  }
   109  // TODO(jlm): add test
   110  // Delete Owner
   111  func (info *ResourceInfo) DeleteOwner(p CombinedPrincipal, mutex *sync.RWMutex) error {
   112  	if mutex != nil {
   113  		mutex.Lock()
   114  		defer mutex.Unlock()
   115  	}
   116  	n := FindCombinedPrincipalPosition(p, info.Owners)
   117  	if n < 0 {
   118  		return nil
   119  	}
   120  	info.Owners[n] = info.Owners[len(info.Owners)-1]
   121  	info.Owners = info.Owners[:len(info.Owners)-1]
   122  	return nil
   123  }
   124  // TODO(jlm): add test
   125  // Delete Reader
   126  func (info *ResourceInfo) DeleteReader(p CombinedPrincipal, mutex *sync.RWMutex) error {
   127  	if mutex != nil {
   128  		mutex.Lock()
   129  		defer mutex.Unlock()
   130  	}
   131  	n := FindCombinedPrincipalPosition(p, info.Readers)
   132  	if n < 0 {
   133  		return nil
   134  	}
   135  	info.Readers[n] = info.Readers[len(info.Readers)-1]
   136  	info.Readers = info.Readers[:len(info.Readers)-1]
   137  	return nil
   138  }
   139  
   140  // TODO(jlm): add test
   141  // Delete Writer.
   142  func (info *ResourceInfo) DeleteWriter(p CombinedPrincipal, mutex *sync.RWMutex) error {
   143  	if mutex != nil {
   144  		mutex.Lock()
   145  		defer mutex.Unlock()
   146  	}
   147  	n := FindCombinedPrincipalPosition(p, info.Writers)
   148  	if n < 0 {
   149  		return nil
   150  	}
   151  	// TODO(jlm): add test
   152  	info.Writers[n] = info.Writers[len(info.Owners)-1]
   153  	info.Writers = info.Writers[:len(info.Owners)-1]
   154  	return nil
   155  }
   156  
   157  // FindResource looks up the resource by its name.
   158  func (m *ResourceMasterInfo) FindResource(resourceName string, mutex *sync.RWMutex) *ResourceInfo {
   159  	if mutex != nil {
   160  		mutex.Lock()
   161  		defer mutex.Unlock()
   162  	}
   163  	for i := 0; i < len(m.Resources); i++ {
   164  		if *m.Resources[i].Name == resourceName {
   165  			return m.Resources[i]
   166  		}
   167  	}
   168  	return nil
   169  }
   170  
   171  // InsertResource adds a resource.
   172  func (m *ResourceMasterInfo) InsertResource(info *ResourceInfo, mutex *sync.RWMutex) error {
   173  	if mutex != nil {
   174  		mutex.Lock()
   175  		defer mutex.Unlock()
   176  	}
   177  	l := m.FindResource(*info.Name, nil)
   178  	if l != nil {
   179  		return nil
   180  	}
   181  	m.Resources = append(m.Resources, info)
   182  	return nil
   183  }
   184  
   185  // DeleteResource deletes a resource.
   186  func (m *ResourceMasterInfo) DeleteResource(resourceName string, mutex *sync.RWMutex) error {
   187  	if mutex != nil {
   188  		mutex.Lock()
   189  		defer mutex.Unlock()
   190  	}
   191  	return nil
   192  }
   193  
   194  func (p *PrincipalInfo) PrintPrincipal() {
   195  	if p.Name == nil || p.Cert == nil {
   196  		return
   197  	}
   198  	fmt.Printf("Name: %s\nCertificate: %x\n", *p.Name, p.Cert)
   199  }
   200  
   201  func (cp *CombinedPrincipal) PrintCombinedPrincipal() {
   202  	if cp == nil {
   203  		return
   204  	}
   205  	// principals
   206  	for i := 0; i < len(cp.Principals); i++ {
   207  		cp.Principals[i].PrintPrincipal()
   208  	}
   209  }
   210  
   211  func PrintPrincipalList(pl []*CombinedPrincipal) {
   212  	if pl == nil {
   213  		fmt.Printf("Empty\n")
   214  		return
   215  	}
   216  	for i := 0; i < len(pl); i++ {
   217  		pl[i].PrintCombinedPrincipal()
   218  		fmt.Printf("\n")
   219  	}
   220  }
   221  
   222  // PrintResource prints a resource to the log.
   223  func (r *ResourceInfo) PrintResource(directory string, printContents bool) {
   224  	if r == nil {
   225  		return
   226  	}
   227  	fmt.Printf("\n")
   228  	if r.Name != nil {
   229  		fmt.Printf("Name: %s\n", *r.Name)
   230  	} else {
   231  		fmt.Printf("Name: empty\n");
   232  	}
   233  	if r.Type!= nil {
   234  	fmt.Printf("Type: %d, ", *r.Type)
   235  	} else {
   236  		fmt.Printf("Type: empty, ");
   237  	}
   238  	if r.Size!= nil {
   239  		fmt.Printf("size: %d\n", *r.Size)
   240  	} else {
   241  		fmt.Printf("Size: empty\n");
   242  	}
   243  	if r.DateCreated != nil && r.DateModified != nil {
   244  		fmt.Printf("Created: %s, modified: %s\n", *r.DateCreated, *r.DateModified)
   245  	} else {
   246  		fmt.Printf("Created adn Modified names are empty\n")
   247  	}
   248  	fmt.Printf("Owners: \n")
   249  	PrintPrincipalList(r.Owners)
   250  	fmt.Printf("Readers: \n")
   251  	PrintPrincipalList(r.Readers)
   252  	fmt.Printf("Writers:\n")
   253  	PrintPrincipalList(r.Writers)
   254  	if printContents {
   255  		fileName := path.Join(directory, *r.Name)
   256  		contents, err := r.Read(fileName)
   257  		if err != nil {
   258  			fmt.Printf("File: %s\n", contents)
   259  		}
   260  	}
   261  	fmt.Printf("\n")
   262  }
   263  
   264  // PrintMaster prints the ResourceMaster into the log.
   265  func (m *ResourceMasterInfo) PrintMaster(printResources bool) {
   266  	fmt.Printf("ServiceName: %s\n", *m.ServiceName)
   267  	fmt.Printf("BaseDirectoryName: %s\n", *m.BaseDirectoryName)
   268  	fmt.Printf("PolicyCert: %s\n", m.PolicyCert)
   269  	fmt.Printf("Number of resources: %d\n", len(m.Resources))
   270  	if printResources {
   271  		for i := 0; i < len(m.Resources); i++ {
   272  			m.Resources[i].PrintResource(*m.BaseDirectoryName, true)
   273  			fmt.Printf("\n")
   274  		}
   275  	}
   276  }
   277  
   278  // Read causes the bytes of the file to be decrypted and read to the message
   279  // stream. By the time this function is called, the remote principal has already
   280  // been authenticated and the operation has already been authorized.
   281  func (r *ResourceInfo) Read(directory string) ([]byte, error) {
   282  	var err error
   283  	var out []byte
   284  	filename := path.Join(directory, *r.Name)
   285  	bytes_read, err := ioutil.ReadFile(filename)
   286  	if err != nil {
   287  		return nil, err
   288  	}
   289  	if len(r.Keys) >= 32 {
   290  		out, err = tao.Unprotect(r.Keys, bytes_read)
   291  	} else {
   292  		out = bytes_read
   293  	}
   294  	size := int32(len(out))
   295  	if err == nil {
   296  		r.Size = &size
   297  	}
   298  	return out, err
   299  }
   300  
   301  // Write causes the bytes of the file to be encrypted and integrity-protected
   302  // and written to disk as they are read from the MessageStream.
   303  func (r *ResourceInfo) Write(directory string, fileContents []byte) error {
   304  	filename := path.Join(directory, *r.Name)
   305  	if len(r.Keys) >= 32 {
   306  		// Encrypt
   307  		encrypted, err := tao.Protect(r.Keys, fileContents)
   308  		if err != nil {
   309  		}
   310  		err = ioutil.WriteFile(filename, encrypted, 0644)
   311  		if err == nil {
   312  			size := int32(len(fileContents))
   313  			r.Size = &size
   314  		}
   315  		return err
   316  	} else {
   317  		err := ioutil.WriteFile(filename, fileContents, 0644)
   318  		if err == nil {
   319  			size := int32(len(fileContents))
   320  			r.Size = &size
   321  		}
   322  		return err
   323  	}
   324  }
   325  
   326  func ReadTable(table *ResourceMasterInfo, tableFileName string, fileSecrets []byte, mutex *sync.RWMutex) bool {
   327  	if mutex != nil {
   328  		mutex.Lock()
   329  		defer mutex.Unlock()
   330  	}
   331  	encryptedTable, err := ioutil.ReadFile(tableFileName)
   332  	if err == nil {
   333  		serializedTable, err := tao.Unprotect(fileSecrets, encryptedTable)
   334  		if err != nil {
   335  			return false
   336  		}
   337  		err = proto.Unmarshal(serializedTable, table)
   338  		if err != nil {
   339  			return false
   340  		}
   341  	}
   342  	return true
   343  }
   344  
   345  func SaveTable(table *ResourceMasterInfo, tableFileName string, fileSecrets []byte, mutex *sync.RWMutex) bool {
   346  	if mutex != nil {
   347  		mutex.Lock()
   348  		defer mutex.Unlock()
   349  	}
   350  	serializedTable, err := proto.Marshal(table)
   351  	if err != nil {
   352  		return false
   353  	}
   354  	encryptedTable, err := tao.Protect(fileSecrets, serializedTable)
   355  	if err != nil {
   356  		return false
   357  	}	
   358  	err = ioutil.WriteFile(tableFileName, encryptedTable, 0666)
   359  	if err != nil {
   360  		return false
   361  	}	
   362  	return true
   363  }