From 5fd83771641d15c418f747bd343ba6738d3875f7 Mon Sep 17 00:00:00 2001 From: Cameron Katri Date: Sun, 9 May 2021 14:20:58 -0400 Subject: Import macOS userland adv_cmds-176 basic_cmds-55 bootstrap_cmds-116.100.1 developer_cmds-66 diskdev_cmds-667.40.1 doc_cmds-53.60.1 file_cmds-321.40.3 mail_cmds-35 misc_cmds-34 network_cmds-606.40.1 patch_cmds-17 remote_cmds-63 shell_cmds-216.60.1 system_cmds-880.60.2 text_cmds-106 --- diskdev_cmds/setclass.tproj/setclass.8 | 46 ++++++++++ diskdev_cmds/setclass.tproj/setclass.c | 153 +++++++++++++++++++++++++++++++++ 2 files changed, 199 insertions(+) create mode 100644 diskdev_cmds/setclass.tproj/setclass.8 create mode 100644 diskdev_cmds/setclass.tproj/setclass.c (limited to 'diskdev_cmds/setclass.tproj') diff --git a/diskdev_cmds/setclass.tproj/setclass.8 b/diskdev_cmds/setclass.tproj/setclass.8 new file mode 100644 index 0000000..90d0c80 --- /dev/null +++ b/diskdev_cmds/setclass.tproj/setclass.8 @@ -0,0 +1,46 @@ +.\" Copyright (c) 2010-2012 Apple Inc. All rights reserved. +.\" +.\" The contents of this file constitute Original Code as defined in and +.\" are subject to the Apple Public Source License Version 1.1 (the +.\" "License"). You may not use this file except in compliance with the +.\" License. Please obtain a copy of the License at +.\" http://www.apple.com/publicsource and read it before using this file. +.\" +.\" This 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 OR NON-INFRINGEMENT. Please see the +.\" License for the specific language governing rights and limitations +.\" under the License. +.\" +.\" @(#)setclass.8 +.Dd June 20, 2012 +.Dt SETCLASS 8 +.Os "Mac OS X" +.Sh NAME +.Nm setclass +.Nd content protection utility +.Sh SYNOPSIS +.Nm setclass +.Ar file +.Op A-E +.Sh DESCRIPTION +.Pp +The +.Nm +utility sets and gets the content protection class of a given file. +.Pp +If a class from A to E is specified, +.Nm +will attempt to set +.Ar file +to that class. +If no class is given, +.Nm +will report the current protection class of +.Ar file. +.Pp +Note that the ability to change the content protection class of a file is restricted by the +runtime status of the device in question. If the device is locked with a PIN code, then +you may not be able to modify the protection class, even as root. diff --git a/diskdev_cmds/setclass.tproj/setclass.c b/diskdev_cmds/setclass.tproj/setclass.c new file mode 100644 index 0000000..306547b --- /dev/null +++ b/diskdev_cmds/setclass.tproj/setclass.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2010-2020 Apple Inc. All rights reserved. + */ +#include +#include +#include +#include +#include +#include + +/* from sys/cprotect.h */ + +#define PROTECTION_CLASS_A 1 +#define PROTECTION_CLASS_B 2 +#define PROTECTION_CLASS_C 3 +#define PROTECTION_CLASS_D 4 +#define PROTECTION_CLASS_E 5 +#define PROTECTION_CLASS_F 6 + +void +usage(void) +{ + printf("usage: setclass [A-F]\n"); + printf("\tsets to a protection class from A to F.\n"); + printf("\tIf no class is specified, reports the current class for .\n"); + exit(0); +} + +int +chartoclass(char c) +{ + switch (c) { + /* directory 'unset' operation */ + case '0': + return 0; + case 'A': + case 'a': + return PROTECTION_CLASS_A; + case 'B': + case 'b': + return PROTECTION_CLASS_B; + case 'C': + case 'c': + return PROTECTION_CLASS_C; + case 'D': + case 'd': + return PROTECTION_CLASS_D; + case 'E': + case 'e': + return PROTECTION_CLASS_E; + case 'F': + case 'f': + return PROTECTION_CLASS_F; + default: + usage(); + exit(0); + } + return 0; +} + +char +classtochar(int class) +{ + if (class < 0) { + /* negative classes are invalid */ + return -1; + } + + /* otherwise, it must be >= 0... */ + if (class == 0) { + /* Directories are allowed to be "unset" */ + return 0; + } + return 'A' + (class - 1); +} + +int +main(int argc, char **argv) +{ + int error = 0, class = 0, do_set = 0; + static struct attrlist req = { + .bitmapcount = ATTR_BIT_MAP_COUNT, + .commonattr = ATTR_CMN_DATA_PROTECT_FLAGS + }; + + if ((argc < 2) || (argc > 3)) + usage(); + + if (argv[2]) { + do_set = 1; + class = chartoclass(*argv[2]); + } + + /* + * setclass and getclass for `argv[1]` using setattrlist(2) and + * getattrlist(2) respectively. + */ + if (do_set) { + struct { + uint32_t prot_class; + } __attribute__((packed, aligned(4))) attrs = { + .prot_class = class + }; + + error = setattrlist(argv[1], (void *)&req, &attrs, sizeof(attrs), + FSOPT_NOFOLLOW); + if (error) { + char new_class = classtochar(class); + if (new_class == 0) { + warn("could not set protection class of %s to (directory none)", + argv[1]); + } + else { + warn("could not set protection class of %s to %c", argv[1], + new_class); + } + } + } + else { + req.commonattr |= ATTR_CMN_RETURNED_ATTRS; + + struct { + uint32_t len; + attribute_set_t returned; + uint32_t prot_class; + } __attribute__((packed, aligned(4))) attrs; + + error = getattrlist(argv[1], (void *)&req, &attrs, sizeof(attrs), + FSOPT_NOFOLLOW); + if (error == -1 || attrs.len != sizeof(attrs) || + attrs.returned.commonattr != req.commonattr) { + if (error == -1) { + error = errno; + } + else { + error = EINVAL; + } + err(error, "could not get protection class"); + } + else { + class = attrs.prot_class; + char new_class = classtochar(class); + if (new_class == 0) { + printf("%s is in protection class (directory none) \n", argv[1]); + } + else { + printf("%s is in protection class %c\n", argv[1], new_class); + } + } + } + + return error; +} -- cgit v1.2.3-56-ge451