1/* 2 * Copyright (c) 2006-2013 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 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 11 * file. 12 * 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. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24// 25// csutilities - miscellaneous utilities for the code signing implementation 26// 27// This is a collection of odds and ends that wouldn't fit anywhere else. 28// The common theme is that the contents are otherwise naturally homeless. 29// 30#ifndef _H_CSUTILITIES 31#define _H_CSUTILITIES 32 33#include <Security/Security.h> 34#include <security_utilities/hashing.h> 35#include <security_utilities/unix++.h> 36#include <security_cdsa_utilities/cssmdata.h> 37#include <copyfile.h> 38#include <asl.h> 39#include <cstdarg> 40 41namespace Security { 42namespace CodeSigning { 43 44 45// 46// Test for the canonical Apple CA certificate 47// 48bool isAppleCA(SecCertificateRef cert); 49bool isAppleCA(const Hashing::Byte *sha1); 50 51 52// 53// Calculate canonical hashes of certificate. 54// This is simply defined as (always) the SHA1 hash of the DER. 55// 56void hashOfCertificate(const void *certData, size_t certLength, SHA1::Digest digest); 57void hashOfCertificate(SecCertificateRef cert, SHA1::Digest digest); 58bool verifyHash(SecCertificateRef cert, const Hashing::Byte *digest); 59 60 61// 62// Calculate hashes of (a section of) a file. 63// Starts at the current file position. 64// Extends to end of file, or (if limit > 0) at most limit bytes. 65// Returns number of bytes digested. 66// 67template <class _Hash> 68size_t hashFileData(UnixPlusPlus::FileDesc fd, _Hash *hasher, size_t limit = 0) 69{ 70 unsigned char buffer[4096]; 71 size_t total = 0; 72 for (;;) { 73 size_t size = sizeof(buffer); 74 if (limit && limit < size) 75 size = limit; 76 size_t got = fd.read(buffer, size); 77 total += got; 78 if (fd.atEnd()) 79 break; 80 hasher->update(buffer, got); 81 if (limit && (limit -= got) == 0) 82 break; 83 } 84 return total; 85} 86 87template <class _Hash> 88size_t hashFileData(const char *path, _Hash *hasher) 89{ 90 UnixPlusPlus::AutoFileDesc fd(path); 91 return hashFileData(fd, hasher); 92} 93 94 95// 96// Check to see if a certificate contains a particular field, by OID. This works for extensions, 97// even ones not recognized by the local CL. It does not return any value, only presence. 98// 99bool certificateHasField(SecCertificateRef cert, const CSSM_OID &oid); 100bool certificateHasPolicy(SecCertificateRef cert, const CSSM_OID &policyOid); 101 102 103// 104// Encapsulation of the copyfile(3) API. 105// This is slated to go into utilities once stable. 106// 107class Copyfile { 108public: 109 Copyfile(); 110 ~Copyfile() { copyfile_state_free(mState); } 111 112 operator copyfile_state_t () const { return mState; } 113 114 void set(uint32_t flag, const void *value); 115 void get(uint32_t flag, void *value); 116 117 void operator () (const char *src, const char *dst, copyfile_flags_t flags); 118 119private: 120 void check(int rc); 121 122private: 123 copyfile_state_t mState; 124}; 125 126 127// 128// MessageTracer support 129// 130class MessageTrace { 131public: 132 MessageTrace(const char *domain, const char *signature); 133 ~MessageTrace() { ::asl_free(mAsl); } 134 void add(const char *key, const char *format, ...); 135 void send(const char *format, ...); 136 137private: 138 aslmsg mAsl; 139}; 140 141 142// 143// A reliable uid set/reset bracket 144// 145class UidGuard { 146public: 147 UidGuard() : mPrevious(-1) { } 148 UidGuard(uid_t uid) : mPrevious(-1) { seteuid(uid); } 149 ~UidGuard() 150 { 151 if (active()) 152 UnixError::check(::seteuid(mPrevious)); 153 } 154 155 bool seteuid(uid_t uid) 156 { 157 if (uid == geteuid()) 158 return true; // no change, don't bother the kernel 159 if (!active()) 160 mPrevious = ::geteuid(); 161 return ::seteuid(uid) == 0; 162 } 163 164 bool active() const { return mPrevious != uid_t(-1); } 165 operator bool () const { return active(); } 166 uid_t saved() const { assert(active()); return mPrevious; } 167 168private: 169 uid_t mPrevious; 170}; 171 172 173} // end namespace CodeSigning 174} // end namespace Security 175 176#endif // !_H_CSUTILITIES 177