2 * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
23 * AuthorizationMechEval.cpp
27 #include "AuthorizationMechEval.h"
28 #include <security_utilities/logging.h>
29 #include <bsm/audit_uevents.h>
30 #include <security_utilities/ccaudit.h>
32 namespace Authorization
{
34 AgentMechanismRef::AgentMechanismRef(const AuthHostType type
, Session
&session
) :
35 RefPointer
<QueryInvokeMechanism
>(new QueryInvokeMechanism(type
, session
)) {}
37 // we need the vector<string> of mechanisms
38 AgentMechanismEvaluator::AgentMechanismEvaluator(uid_t uid
, Session
& session
, const vector
<string
>& inMechanisms
) :
39 mMechanisms(inMechanisms
), mClientUid(uid
), mSession(session
)
45 AgentMechanismEvaluator::run(const AuthValueVector
&inArguments
, const AuthItemSet
&inHints
, const AuthorizationToken
&auth
)
47 const AuthItemSet
&inContext
= const_cast<AuthorizationToken
&>(auth
).infoSet();
49 // add process specifics to context?
51 vector
<std::string
>::const_iterator currentMechanism
= mMechanisms
.begin();
53 AuthorizationResult result
= kAuthorizationResultAllow
;
55 AuthItemSet hints
= inHints
;
56 AuthItemSet context
= inContext
;
58 while ( (result
== kAuthorizationResultAllow
) &&
59 (currentMechanism
!= mMechanisms
.end()) ) // iterate mechanisms
61 ClientMap::iterator iter
= mClients
.find(*currentMechanism
);
62 if (iter
== mClients
.end())
64 string::size_type extPlugin
= currentMechanism
->find(':');
65 if (extPlugin
!= string::npos
)
67 // no whitespace removal
68 string
pluginIn(currentMechanism
->substr(0, extPlugin
));
69 string mechanismIn
, authhostIn
;
71 string::size_type extMechanism
= currentMechanism
->rfind(',');
72 AuthHostType hostType
= securityAgent
;
74 if (extMechanism
!= string::npos
)
76 if (extMechanism
< extPlugin
)
77 return errAuthorizationInternal
;
79 mechanismIn
= currentMechanism
->substr(extPlugin
+ 1, extMechanism
- extPlugin
- 1);
80 authhostIn
= currentMechanism
->substr(extMechanism
+ 1);
81 if (authhostIn
== "privileged")
82 hostType
= privilegedAuthHost
;
85 mechanismIn
= currentMechanism
->substr(extPlugin
+ 1);
87 secdebug("AuthEvalMech", "external mechanism %s:%s", pluginIn
.c_str(), mechanismIn
.c_str());
89 AgentMechanismRef
client(hostType
, mSession
);
90 client
->initialize(pluginIn
, mechanismIn
, inArguments
);
91 mClients
.insert(ClientMap::value_type(*currentMechanism
, client
));
93 else if (*currentMechanism
== "authinternal")
95 secdebug("AuthEvalMech", "performing authentication");
96 result
= authinternal(context
);
98 AuthItem
*rightItem
= hints
.find(AGENT_HINT_AUTHORIZE_RIGHT
);
99 string right
= (rightItem
== NULL
) ? string("<unknown right>") : rightItem
->stringValue();
100 CommonCriteria::AuditRecord
auditrec(auth
.creatorAuditToken());
101 if (kAuthorizationResultAllow
== result
)
102 auditrec
.submit(AUE_ssauthint
, CommonCriteria::errNone
, right
.c_str());
103 else // kAuthorizationResultDeny
104 auditrec
.submit(AUE_ssauthint
, CommonCriteria::errInvalidCredential
, right
.c_str());
106 else if (*currentMechanism
== "push_hints_to_context")
108 secdebug("AuthEvalMech", "evaluate push_hints_to_context");
109 // doesn't block evaluation, ever
110 result
= kAuthorizationResultAllow
;
114 return errAuthorizationInternal
;
117 iter
= mClients
.find(*currentMechanism
);
118 if (iter
!= mClients
.end())
122 AgentMechanismRef
&client
= iter
->second
;
123 client
->run(inArguments
, hints
, context
, &result
);
125 bool interrupted
= false;
126 while (client
->state() == client
->current
)
128 // check for interruption
129 vector
<std::string
>::const_iterator checkMechanism
= mMechanisms
.begin();
130 while (*checkMechanism
!= *currentMechanism
) {
131 ClientMap::iterator iter2
= mClients
.find(*checkMechanism
);
132 if (iter2
->second
->state() == iter2
->second
->interrupting
)
134 client
->deactivate();
135 // nothing can happen until the client mechanism returns control to us
136 while (client
->state() == client
->deactivating
)
139 secdebug("AuthEvalMech", "evaluate(%s) interrupted by %s.", (iter
->first
).c_str(), (iter2
->first
).c_str());
142 hints
= iter2
->second
->inHints();
143 context
= iter2
->second
->inContext();
144 currentMechanism
= checkMechanism
;
150 if (client
->state() == client
->current
)
156 // clear reason for restart from interrupt
157 uint32_t reason
= SecurityAgent::worldChanged
;
158 AuthItemRef
retryHint(AGENT_HINT_RETRY_REASON
, AuthValueOverlay(sizeof(reason
), &reason
));
159 hints
.erase(retryHint
); hints
.insert(retryHint
); // replace
161 result
= kAuthorizationResultAllow
;
165 secdebug("AuthEvalMech", "evaluate(%s) with result: %lu.", (iter
->first
).c_str(), result
);
168 secdebug("AuthEvalMech", "exception during evaluate(%s).", (iter
->first
).c_str());
169 result
= kAuthorizationResultUndefined
;
173 if (result
== kAuthorizationResultAllow
)
177 if ((result
== kAuthorizationResultUserCanceled
) ||
178 (result
== kAuthorizationResultAllow
))
184 // convert AuthorizationResult to OSStatus
187 case kAuthorizationResultDeny
:
188 return errAuthorizationDenied
;
189 case kAuthorizationResultUserCanceled
:
190 return errAuthorizationCanceled
;
191 case kAuthorizationResultAllow
:
192 return errAuthorizationSuccess
;
194 return errAuthorizationInternal
;
198 AuthorizationResult
AgentMechanismEvaluator::authinternal(AuthItemSet
&context
)
200 secdebug("AuthEvalMech", "evaluate authinternal");
202 AuthItemSet::iterator found
= find_if(context
.begin(), context
.end(), FindAuthItemByRightName(kAuthorizationEnvironmentUsername
) );
203 if (found
== context
.end())
205 string
username(static_cast<const char *>((*found
)->value().data
), (*found
)->value().length
);
206 secdebug("AuthEvalMech", "found username");
207 found
= find_if(context
.begin(), context
.end(), FindAuthItemByRightName(kAuthorizationEnvironmentPassword
) );
208 if (found
== context
.end())
210 string
password(static_cast<const char *>((*found
)->value().data
), (*found
)->value().length
);
211 secdebug("AuthEvalMech", "found password");
213 // Call to checkpw in DS
214 Server::active().longTermActivity();
215 Credential
newCredential(username
, password
, true); // create a new shared credential
217 if (newCredential
->isValid())
219 Syslog::info("authinternal authenticated user %s (uid %lu).", newCredential
->username().c_str(), newCredential
->uid());
220 return kAuthorizationResultAllow
;
223 Syslog::error("authinternal failed to authenticate user %s.", newCredential
->username().c_str());
227 return kAuthorizationResultDeny
;
232 AgentMechanismEvaluator::commonHints(const AuthorizationToken &auth)
238 } /* namespace Authorization */