cs_misc.cpp   [plain text]


/*
 * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved.
 * 
 * @APPLE_LICENSE_HEADER_START@
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this
 * file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 * 
 * @APPLE_LICENSE_HEADER_END@
 */

//
// cs_misc - codesign miscellaneous operations
//
#include "codesign.h"
#include <libproc.h>
#include <sys/codesign.h>
#include <sys/param.h>		// MAXPATHLEN


using namespace CodeSigning;
using namespace UnixPlusPlus;


//
// 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 = 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");
	} else {
		fail("%s: not a numeric process id", target);
	}
}


//
// Directly tell the kernel to manipulate a process's Code Signing state.
// This better be only of interest to geeks and testers.
//
void procaction(const char *target)
{
	if (pid_t pid = atol(target)) {
		int rc;
		if (!strncmp(procAction, "invalidate", strlen(procAction)))
			rc = ::csops(pid, CS_OPS_MARKINVALID, NULL, 0);
		else if (!strncmp(procAction, "hard", strlen(procAction)))
			rc = ::csops(pid, CS_OPS_MARKHARD, NULL, 0);
		else if (!strncmp(procAction, "kill", strlen(procAction)))
			rc = ::csops(pid, CS_OPS_MARKKILL, NULL, 0);
		else if (int op = atol(procAction))
			rc = ::csops(pid, op, NULL, 0);
		else
			fail("%s: not a recognized operation", procAction);
		if (rc == -1)
			perror(target);
		else if (verbose)
			procinfo(target);
	} else {
		fail("%s: not a numeric process id", target);
	}
}