1/*
2 * Copyright (c) 2002-2004 Apple Computer, 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// Password.cpp
26//
27#include "Password.h"
28#include <Security/SecBase.h>
29#include "SecBridge.h"
30
31#include "KCCursor.h"
32
33using namespace KeychainCore;
34using namespace CssmClient;
35
36PasswordImpl::PasswordImpl(SecItemClass itemClass, SecKeychainAttributeList *searchAttrList, SecKeychainAttributeList *itemAttrList) :
37    mItem(itemClass, itemAttrList, 0, NULL), mUseKeychain(false), mFoundInKeychain(false), mRememberInKeychain(false), mMutex(Mutex::recursive)
38{
39    if (searchAttrList && itemAttrList)
40    {
41        mUseKeychain = true;
42        mKeychain = Keychain::optional(NULL);
43		mRememberInKeychain = true;
44
45        // initialize mFoundInKeychain to true if mItem is found
46
47        StorageManager::KeychainList keychains;
48        globals().storageManager.optionalSearchList(NULL, keychains);
49        KCCursor cursor(keychains, itemClass, searchAttrList);
50
51        if (cursor->next(mItem))
52            mFoundInKeychain = true;
53    }
54}
55
56PasswordImpl::PasswordImpl(PasswordImpl& existing)
57{
58	mKeychain = existing.mKeychain;
59	mItem = existing.mItem;
60    mUseKeychain = existing.mUseKeychain;
61    mFoundInKeychain = existing.mFoundInKeychain;
62    mRememberInKeychain = existing.mRememberInKeychain;
63}
64
65
66
67PasswordImpl::~PasswordImpl() throw()
68{
69}
70
71void
72PasswordImpl::setAccess(Access *access)
73{
74    // changing an existing ACL is more work than this SPI wants to do
75    if (!mFoundInKeychain)
76        mItem->setAccess(access);
77}
78
79void
80PasswordImpl::setData(UInt32 length, const void *data)
81{
82    assert(mUseKeychain);
83
84    // do different things based on mFoundInKeychain?
85    mItem->setData(length,data);
86}
87
88bool
89PasswordImpl::getData(UInt32 *length, const void **data)
90{
91    if (mItem->isPersistent())
92    {
93        // try to retrieve it
94        CssmDataContainer outData;
95        try
96        {
97            mItem->getData(outData);
98            if (length && data)
99            {
100                *length=(uint32)outData.length();
101                outData.Length=0;
102                *data=outData.data();
103                outData.Data=NULL;
104            }
105            return true;
106        }
107        catch (...)
108        {
109            // cancel unlock: CSP_USER_CANCELED
110            // deny rogue app CSP_OPERATION_AUTH_DENIED
111            return false;
112        }
113    }
114    else
115        return false;
116}
117
118void
119PasswordImpl::save()
120{
121    assert(mUseKeychain);
122
123    if (mFoundInKeychain)
124    {
125        mItem->update();
126    }
127    else
128    {
129        mKeychain->add(mItem);
130
131        // reinitialize mItem now it's on mKeychain
132        mFoundInKeychain = true; // should be set by member that resets mItem
133    }
134}
135
136Password::Password(SecItemClass itemClass, SecKeychainAttributeList *searchAttrList, SecKeychainAttributeList *itemAttrList) :
137    SecPointer<PasswordImpl>(new PasswordImpl(itemClass, searchAttrList, itemAttrList))
138{
139}
140
141Password::Password(PasswordImpl *impl) : SecPointer<PasswordImpl>(impl)
142{
143}
144
145Password::Password(PasswordImpl &impl) : SecPointer<PasswordImpl>(new PasswordImpl(impl))
146{
147}
148