]>
git.saurik.com Git - apple/security.git/blob - OSX/include/security_codesigning/filediskrep.cpp
   2  * Copyright (c) 2006-2007,2011 Apple Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. Please obtain a copy of the License at 
  10  * http://www.opensource.apple.com/apsl/ and read it before using this 
  13  * The Original Code and all software distributed under the License are 
  14  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  15  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  16  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  17  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  18  * Please see the License for the specific language governing rights and 
  19  * limitations under the License. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  23 #include "filediskrep.h" 
  24 #include "StaticCode.h" 
  25 #include <security_utilities/macho++.h> 
  30 namespace CodeSigning 
{ 
  32 using namespace UnixPlusPlus
; 
  36 // Everything's lazy in here 
  38 FileDiskRep::FileDiskRep(const char *path
) 
  41         CODESIGN_DISKREP_CREATE_FILE(this, (char*)path
); 
  46 // Produce an extended attribute name from a canonical slot name 
  48 string 
FileDiskRep::attrName(const char *name
) 
  50         static const char prefix
[] = "com.apple.cs."; 
  51         return string(prefix
) + name
; 
  56 // Retrieve an extended attribute by name 
  58 CFDataRef 
FileDiskRep::getAttribute(const char *name
) 
  60         string aname 
= attrName(name
); 
  62                 ssize_t length 
= fd().getAttrLength(aname
); 
  64                         return NULL
;            // no such attribute 
  65                 CFMallocData 
buffer(length
); 
  66                 fd().getAttr(aname
, buffer
, length
); 
  68         } catch (const UnixError 
&err
) { 
  69                 // recover some errors that happen in (relatively) benign circumstances 
  71                 case ENOTSUP
:   // no extended attributes on this filesystem 
  72                 case EPERM
:             // filesystem objects to name(?) 
  82 // Extract and return a component by slot number. 
  83 // If we have a Mach-O binary, use embedded components. 
  84 // Otherwise, look for and return the extended attribute, if any. 
  86 CFDataRef 
FileDiskRep::component(CodeDirectory::SpecialSlot slot
) 
  88         if (const char *name 
= CodeDirectory::canonicalSlotName(slot
)) 
  89                 return getAttribute(name
); 
  96 // Generate a suggested set of internal requirements. 
  97 // We don't really have to say much. However, if we encounter a file that 
  98 // starts with the magic "#!" script marker, we do suggest that this should 
  99 // be a valid host if we can reasonably make out what that is. 
 101 const Requirements 
*FileDiskRep::defaultRequirements(const Architecture 
*, const SigningContext 
&ctx
) 
 103         // read start of file 
 105         size_t length 
= fd().read(buffer
, sizeof(buffer
), 0); 
 106         if (length 
> 3 && buffer
[0] == '#' && buffer
[1] == '!' && buffer
[2] == '/') { 
 107                 // isolate (full) path element in #!/full/path -some -other -stuff 
 108                 if (length 
== sizeof(buffer
)) 
 110                 buffer
[length
] = '\0'; 
 111                 char *cmd 
= buffer 
+ 2; 
 112                 cmd
[strcspn(cmd
, " \t\n\r\f")] = '\0'; 
 113                 secdebug("filediskrep", "looks like a script for %s", cmd
); 
 116                                 // find path on disk, get designated requirement (if signed) 
 117                                 string path 
= ctx
.sdkPath(cmd
); 
 118                                 if (RefPointer
<DiskRep
> rep 
= DiskRep::bestFileGuess(path
)) 
 119                                         if (SecPointer
<SecStaticCode
> code 
= new SecStaticCode(rep
)) 
 120                                                 if (const Requirement 
*req 
= code
->designatedRequirement()) { 
 121                                                         CODESIGN_SIGN_DEP_INTERP(this, (char*)cmd
, (void*)req
); 
 122                                                         // package up as host requirement and return that 
 123                                                         Requirements::Maker maker
; 
 124                                                         maker
.add(kSecHostRequirementType
, req
->clone()); 
 128                                 secdebug("filediskrep", "exception getting host requirement (ignored)"); 
 135 string 
FileDiskRep::format() 
 142 // FileDiskRep::Writers 
 144 DiskRep::Writer 
*FileDiskRep::writer() 
 146         return new Writer(this); 
 151 // Write a component. 
 152 // Note that this isn't concerned with Mach-O writing; this is handled at 
 153 // a much higher level. If we're called, it's extended attribute time. 
 155 void FileDiskRep::Writer::component(CodeDirectory::SpecialSlot slot
, CFDataRef data
) 
 158                 fd().setAttr(attrName(CodeDirectory::canonicalSlotName(slot
)), 
 159                         CFDataGetBytePtr(data
), CFDataGetLength(data
)); 
 160         } catch (const UnixError 
&error
) { 
 161                 if (error
.error 
== ERANGE
) 
 162                         MacOSError::throwMe(errSecCSCMSTooLarge
); 
 169 // Clear all signing data 
 171 void FileDiskRep::Writer::remove() 
 173         for (CodeDirectory::SpecialSlot slot 
= 0; slot 
< cdSlotCount
; slot
++) 
 174                 if (const char *name 
= CodeDirectory::canonicalSlotName(slot
)) 
 175                         fd().removeAttr(attrName(name
)); 
 176         fd().removeAttr(attrName(kSecCS_SIGNATUREFILE
)); 
 181 // We are NOT the preferred store for components because our approach 
 182 // (extended attributes) suffers from some serious limitations. 
 184 bool FileDiskRep::Writer::preferredStore() 
 190 } // end namespace CodeSigning 
 191 } // end namespace Security