BlobCore *BlobCore::readBlob(std::FILE *file, uint32_t magic, size_t minSize, size_t maxSize) { BlobCore header; if (::fread(&header, sizeof(header), 1, file) == 1) if (header.validateBlob(magic, minSize, maxSize)) if (BlobCore *blob = (BlobCore *)malloc(header.length())) { memcpy(blob, &header, sizeof(header)); if (::fread(blob+1, header.length() - sizeof(header), 1, file) == 1) return blob; free(blob); errno = EINVAL; } return NULL; }
BlobCore *BlobCore::readBlob(int fd, uint32_t magic, size_t minSize, size_t maxSize) { BlobCore header; if (::read(fd, &header, sizeof(header)) == sizeof(header)) if (header.validateBlob(magic, minSize, maxSize)) if (BlobCore *blob = (BlobCore *)malloc(header.length())) { memcpy(blob, &header, sizeof(header)); size_t remainder = header.length() - sizeof(header); if (::read(fd, blob+1, remainder) == ssize_t(remainder)) return blob; free(blob); errno = EINVAL; } return NULL; }
// // Provide low-level Code Signing information from the kernel. // This is only of interest to geeks and testers. // void procinfo(const char *target) { if (pid_t pid = (pid_t)atol(target)) { char path[MAXPATHLEN * 2]; uint32_t flags; int rcpath = ::proc_pidpath(pid, path, sizeof(path)); int rcstatus = ::csops(pid, CS_OPS_STATUS, &flags, 0); if (rcpath == 0 && rcstatus == -1) { // neither path nor status (probably bad pid) perror(target); exit(1); } printf("%d:", pid); if (rcpath == 0) printf(" [path:%s]", strerror(errno)); else printf(" %s", path); if (rcstatus == -1) { printf(" [flags:%s]", strerror(errno)); } else { if (flags & CS_VALID) printf(" VALID"); if (flags & CS_HARD) printf(" HARD"); if (flags & CS_KILL) printf(" KILL"); if (flags & CS_EXEC_SET_HARD) printf(" HARD(exec)"); if (flags & CS_EXEC_SET_KILL) printf(" KILL(exec)"); if (flags & ~(CS_VALID|CS_HARD|CS_KILL|CS_EXEC_SET_HARD|CS_EXEC_SET_KILL)) printf(" (0x%x)", flags); } SHA1::Digest hash; int rchash = ::csops(pid, CS_OPS_CDHASH, hash, sizeof(hash)); if (rchash == -1) printf(" [cdhash:%s]", strerror(errno)); else printf(" cdhash=%s", hashString(hash).c_str()); printf("\n"); if (verbose > 0) { BlobCore header; int rcent = ::csops(pid, CS_OPS_ENTITLEMENTS_BLOB, &header, sizeof(header)); // size request if (rcent == 0) printf("[no entitlement]\n"); else if (errno == ERANGE) { // kernel returns a blob header with magic == 0, length == needed size assert(header.magic() == 0); uint32_t bufferLen = (uint32_t)header.length(); if (bufferLen > 1024 * 1024) fail("insane entitlement length from kernel"); uint8_t buffer[bufferLen]; rcent = ::csops(pid, CS_OPS_ENTITLEMENTS_BLOB, buffer, bufferLen); if (rcent == 0) { // kernel says it's good const BlobCore *blob = (const BlobCore *)buffer; if (blob->length() < sizeof(*blob)) fail("runt entitlement blob returned from kernel"); if (blob->magic() == kSecCodeMagicEntitlement) fwrite(blob+1, blob->length() - sizeof(*blob), 1, stdout); else printf("Entitlement blob type 0x%x not understood\n", blob->magic()); } else printf("[entitlements:%s]\n", strerror(errno)); } else printf("[entitlements:%s]\n", strerror(errno)); } } else { fail("%s: not a numeric process id", target); } }