2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
20 // passphrases - canonical code to obtain passphrases
22 #include "agentquery.h"
25 using namespace SecurityAgent
;
29 // Construct a query object
31 SecurityAgentQuery::SecurityAgentQuery()
33 // this may take a while
34 Server::active().longTermActivity();
35 Server::connection().useAgent(this);
38 SecurityAgentQuery::~SecurityAgentQuery()
40 Server::connection(true).useAgent(NULL
);
45 // Perform the "rogue app" access query dialog
47 void QueryKeychainUse::operator () (const char *database
, const char *description
,
48 AclAuthorization action
)
50 queryKeychainAccess(Server::connection().process
.clientCode(),
51 Server::connection().process
.pid(),
52 database
, description
, action
, *this);
57 // Obtain passphrases and submit them to the accept() method until it is accepted
58 // or we can't get another passphrase. Accept() should consume the passphrase
59 // if it is accepted. If no passphrase is acceptable, throw out of here.
61 void QueryPassphrase::query(const AccessCredentials
*cred
, CSSM_SAMPLE_TYPE sampleType
)
63 CssmAutoData
passphrase(CssmAllocator::standard(CssmAllocator::sensitive
));
64 if (SecurityServerAcl::getBatchPassphrase(cred
, sampleType
, passphrase
)) {
65 // batch use - try the one and only, fail if unacceptable
66 if (accept(passphrase
, false) == noReason
)
69 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PASSPHRASE
); //@@@ not ideal
71 // interactive use - run a try/retry loop
72 unsigned int retryCount
= 0;
73 queryInteractive(passphrase
);
74 while (Reason reason
= accept(passphrase
, true)) {
75 if (++retryCount
> maxRetries
) {
76 cancelStagedQuery(tooManyTries
);
77 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PASSPHRASE
); //@@@ not ideal
79 retryInteractive(passphrase
, reason
);
89 // Get existing passphrase (unlock) Query
91 void QueryUnlock::operator () (const AccessCredentials
*cred
)
93 query(cred
, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK
);
96 Reason
QueryUnlock::accept(CssmManagedData
&passphrase
, bool)
98 return database
.decode(passphrase
) ? noReason
: invalidPassphrase
;
101 void QueryUnlock::queryInteractive(CssmOwnedData
&passphrase
)
103 char passString
[maxPassphraseLength
];
104 queryUnlockDatabase(Server::connection().process
.clientCode(),
105 Server::connection().process
.pid(),
106 database
.dbName(), passString
);
107 passphrase
.copy(passString
, strlen(passString
));
110 void QueryUnlock::retryInteractive(CssmOwnedData
&passphrase
, Reason reason
)
112 char passString
[maxPassphraseLength
];
113 retryUnlockDatabase(reason
, passString
);
114 passphrase
.copy(passString
, strlen(passString
));
119 // Get new passphrase Query
121 void QueryNewPassphrase::operator () (const AccessCredentials
*cred
, CssmOwnedData
&passphrase
)
123 query(cred
, CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK
);
124 passphrase
= mPassphrase
;
127 Reason
QueryNewPassphrase::accept(CssmManagedData
&passphrase
, bool canRetry
)
129 //@@@ acceptance criteria are currently hardwired here
130 //@@@ This validation presumes ASCII - UTF8 might be more lenient
132 // if we can't retry (i.e. batch environment), accept it rather than fail terminally
134 mPassphrase
= passphrase
;
138 // if the user insists (re-enters the same passphrase), allow it
139 if (mPassphraseValid
&& passphrase
.get() == mPassphrase
)
142 // check simple criteria
143 mPassphrase
= passphrase
;
144 mPassphraseValid
= true;
145 if (mPassphrase
.length() == 0)
146 return passphraseIsNull
;
147 const char *passString
= mPassphrase
;
148 if (strlen(passString
) < 6)
149 return passphraseTooSimple
;
155 void QueryNewPassphrase::queryInteractive(CssmOwnedData
&passphrase
)
157 char passString
[maxPassphraseLength
];
158 queryNewPassphrase(Server::connection().process
.clientCode(),
159 Server::connection().process
.pid(),
160 dbCommon
.dbName(), initialReason
, passString
);
161 passphrase
.copy(passString
, strlen(passString
));
164 void QueryNewPassphrase::retryInteractive(CssmOwnedData
&passphrase
, Reason reason
)
166 char passString
[maxPassphraseLength
];
167 retryNewPassphrase(reason
, passString
);
168 passphrase
.copy(passString
, strlen(passString
));
173 // Authorize by group membership
175 void QueryAuthorizeByGroup::cancel(Reason reason
)
178 cancelStagedQuery(reason
);
183 void QueryAuthorizeByGroup::done()
191 uid_t
QueryAuthorizeByGroup::uid()
193 return Server::connection().process
.uid();
196 bool QueryAuthorizeByGroup::operator () (const char *group
, const char *candidateUser
,
197 char username
[maxUsernameLength
], char passphrase
[maxPassphraseLength
], Reason reason
)
200 return retryAuthorizationAuthenticate(reason
, username
, passphrase
);
202 bool result
= authorizationAuthenticate(Server::connection().process
.clientCode(),
203 Server::connection().process
.pid(), group
, candidateUser
, username
, passphrase
);