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_secret - secret-validation password ACLs framework.
27//
28#include <security_cdsa_utilities/acl_secret.h>
29#include <security_utilities/trackingallocator.h>
30#include <security_utilities/debugging.h>
31#include <security_utilities/endian.h>
32#include <algorithm>
33
34
35//
36// Construct a secret-bearing ACL subject
37//
38SecretAclSubject::SecretAclSubject(Allocator &alloc,
39		CSSM_ACL_SUBJECT_TYPE type, const CssmData &password)
40	: SimpleAclSubject(type), allocator(alloc),
41	  mSecret(alloc, password), mSecretValid(true), mCacheSecret(false)
42{ }
43
44SecretAclSubject::SecretAclSubject(Allocator &alloc,
45		CSSM_ACL_SUBJECT_TYPE type, CssmManagedData &password)
46    : SimpleAclSubject(type), allocator(alloc),
47	  mSecret(alloc, password), mSecretValid(true), mCacheSecret(false)
48{ }
49
50SecretAclSubject::SecretAclSubject(Allocator &alloc,
51		CSSM_ACL_SUBJECT_TYPE type, bool doCache)
52	: SimpleAclSubject(type), allocator(alloc),
53	  mSecret(alloc), mSecretValid(false), mCacheSecret(doCache)
54{ }
55
56
57//
58// Set the secret after creation.
59//
60// These are const methods by design, even though they obvious (may) set
61// a field in the SecretAclSubject. The fields are mutable, following the
62// general convention that transient state in AclSubjects is mutable.
63//
64void SecretAclSubject::secret(const CssmData &s) const
65{
66	assert(!mSecretValid);	// can't re-set it
67	if (mCacheSecret) {
68		mSecret = s;
69		mSecretValid = true;
70		secdebug("aclsecret", "%p secret stored", this);
71	} else
72		secdebug("aclsecret", "%p refused to store secret", this);
73}
74
75void SecretAclSubject::secret(CssmManagedData &s) const
76{
77	assert(!mSecretValid);	// can't re-set it
78	if (mCacheSecret) {
79		mSecret = s;
80		mSecretValid = true;
81		secdebug("aclsecret", "%p secret stored", this);
82	} else
83		secdebug("aclsecret", "%p refused to store secret", this);
84}
85
86
87//
88// Validate a secret.
89// The subclass has to come up with the secret somehow. We just validate it.
90//
91bool SecretAclSubject::validate(const AclValidationContext &context,
92    const TypedList &sample) const
93{
94	CssmAutoData secret(allocator);
95
96	// try to get the secret; fail if we can't
97	if (!getSecret(context, sample, secret))
98		return false;
99
100	// now validate the secret
101	if (mSecretValid) {
102		return mSecret == secret;
103	} else if (Environment *env = context.environment<Environment>()) {
104		TrackingAllocator alloc(Allocator::standard());
105		TypedList data(alloc, type(), new(alloc) ListElement(secret.get()));
106		CssmSample sample(data);
107		AccessCredentials cred((SampleGroup(sample)), context.credTag());
108		return env->validateSecret(this, &cred);
109	} else {
110		return false;
111	}
112}
113
114
115#ifdef DEBUGDUMP
116
117void SecretAclSubject::debugDump() const
118{
119	if (mSecretValid) {
120		Debug::dump(" ");
121		Debug::dumpData(mSecret.data(), mSecret.length());
122	}
123	if (mCacheSecret)
124		Debug::dump("; CACHING");
125}
126
127#endif //DEBUGDUMP
128