1/*
2 * Copyright (c) 2000-2004,2006,2011,2014 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//
26// acl_process - Process-attribute ACL subject type.
27//
28#include <security_cdsa_utilities/acl_process.h>
29#include <security_utilities/endian.h>
30#include <algorithm>
31
32
33//
34// Validate a credential set against this subject.
35// No credential is required for this match.
36//
37bool ProcessAclSubject::validate(const AclValidationContext &context) const
38{
39    // reality check (internal structure was validated when created)
40    assert(select.uses(CSSM_ACL_MATCH_BITS));
41
42    // access the environment
43    Environment *env = context.environment<Environment>();
44    if (env == NULL) {
45        static Environment localEnvironment;
46        env = &localEnvironment;
47    }
48
49    // match uid
50    if (select.uses(CSSM_ACL_MATCH_UID)) {
51        uid_t uid = env->getuid();
52        if (!(uid == select.uid || (select.uses(CSSM_ACL_MATCH_HONOR_ROOT) && uid == 0)))
53            return false;
54    }
55
56    // match gid
57    if (select.uses(CSSM_ACL_MATCH_GID) && select.gid != env->getgid())
58        return false;
59
60    return true;
61}
62
63
64//
65// Make a copy of this subject in CSSM_LIST form
66//
67CssmList ProcessAclSubject::toList(Allocator &alloc) const
68{
69    // all associated data is public (no secrets)
70    //@@@ ownership of selector data is murky; revisit after leak-plugging pass
71    CssmData sData(memcpy(alloc.alloc<CSSM_ACL_PROCESS_SUBJECT_SELECTOR>(),
72        &select, sizeof(select)), sizeof(select));
73	return TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_PROCESS,
74        new(alloc) ListElement(sData));
75}
76
77
78//
79// Create a ProcessAclSubject
80//
81ProcessAclSubject *ProcessAclSubject::Maker::make(const TypedList &list) const
82{
83    // crack input apart
84	ListElement *selectorData;
85	crack(list, 1, &selectorData, CSSM_LIST_ELEMENT_DATUM);
86    AclProcessSubjectSelector selector;
87    selectorData->extract(selector);
88
89    // validate input
90    if (selector.version != CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION)
91        CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE);
92    if (!selector.uses(CSSM_ACL_MATCH_BITS))
93        CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE);
94
95    // okay
96	return new ProcessAclSubject(selector);
97}
98
99ProcessAclSubject *ProcessAclSubject::Maker::make(Version, Reader &pub, Reader &priv) const
100{
101    AclProcessSubjectSelector selector; pub(selector);
102	n2hi(selector.version);
103	n2hi(selector.mask);
104	n2hi(selector.uid);
105	n2hi(selector.gid);
106	return new ProcessAclSubject(selector);
107}
108
109
110//
111// Export the subject to a memory blob
112//
113void ProcessAclSubject::exportBlob(Writer::Counter &pub, Writer::Counter &priv)
114{
115    pub(select);
116}
117
118void ProcessAclSubject::exportBlob(Writer &pub, Writer &priv)
119{
120	AclProcessSubjectSelector temp;
121	temp.version = h2n (select.version);
122	temp.mask = h2n (select.mask);
123	temp.uid = h2n (select.uid);
124	temp.gid = h2n (select.gid);
125    pub(temp);
126}
127
128
129//
130// Implement the default methods of a ProcessEnvironment
131//
132uid_t ProcessAclSubject::Environment::getuid() const
133{
134    return ::getuid();
135}
136
137gid_t ProcessAclSubject::Environment::getgid() const
138{
139    return ::getgid();
140}
141
142
143#ifdef DEBUGDUMP
144
145void ProcessAclSubject::debugDump() const
146{
147	Debug::dump("Process ");
148	if (select.uses(CSSM_ACL_MATCH_UID)) {
149		Debug::dump("uid=%d", int(select.uid));
150		if (select.uses(CSSM_ACL_MATCH_HONOR_ROOT))
151			Debug::dump("+root");
152	}
153	if (select.uses(CSSM_ACL_MATCH_GID))
154		Debug::dump("gid=%d", int(select.gid));
155}
156
157#endif //DEBUGDUMP
158