]> git.saurik.com Git - apple/security.git/blobdiff - SecurityServer/connection.cpp
Security-222.tar.gz
[apple/security.git] / SecurityServer / connection.cpp
diff --git a/SecurityServer/connection.cpp b/SecurityServer/connection.cpp
deleted file mode 100644 (file)
index 7d8a9d6..0000000
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
- * 
- * The contents of this file constitute Original Code as defined in and are
- * subject to the Apple Public Source License Version 1.2 (the 'License').
- * You may not use this file except in compliance with the License. Please obtain
- * a copy of the License at http://www.apple.com/publicsource and read it before
- * using this file.
- * 
- * This Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
- * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
- * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
- * specific language governing rights and limitations under the License.
- */
-
-
-//
-// connection - manage connections to clients.
-//
-// Note that Connection objects are single-threaded; only one request can be outstanding
-// per connection. The various operational calls (e.g. generateMac) can be called by
-// multiple threads, but each call will be for a different connection (the one the request
-// came in on). Thus, locking happens elsewhere as needed.
-//
-#include "connection.h"
-#include "key.h"
-#include "server.h"
-#include "session.h"
-#include <Security/keyclient.h>
-#include <Security/genkey.h>
-#include <Security/wrapkey.h>
-#include <Security/signclient.h>
-#include <Security/macclient.h>
-#include <Security/cryptoclient.h>
-
-
-//
-// Construct a Connection object.
-//
-Connection::Connection(Process &proc, Port rPort)
- : process(proc), mClientPort(rPort), state(idle), agentWait(NULL),
-   aclUpdateTrigger(NULL)
-{
-       // bump the send-rights count on the reply port so we keep the right after replying
-       mClientPort.modRefs(MACH_PORT_RIGHT_SEND, +1);
-       
-       secdebug("SS", "New connection %p for process %d clientport=%d",
-               this, process.pid(), int(rPort));
-}
-
-
-//
-// When a Connection's destructor executes, the connection must already have been
-// terminated. All we have to do here is clean up a bit.
-//
-Connection::~Connection()
-{
-       secdebug("SS", "Connection %p destroyed", this);
-       assert(!agentWait);
-}
-
-
-//
-// Terminate a Connection normally.
-// This is assumed to be properly sequenced, so no thread races are possible.
-//
-void Connection::terminate()
-{
-       // cleanly discard port rights
-       assert(state == idle);
-       mClientPort.modRefs(MACH_PORT_RIGHT_SEND, -1);  // discard surplus send right
-       assert(mClientPort.getRefs(MACH_PORT_RIGHT_SEND) == 1); // one left for final reply
-       secdebug("SS", "Connection %p terminated", this);
-}
-
-
-//
-// Abort a Connection.
-// This may be called from thread A while thread B is working a request for the Connection,
-// so we must be careful.
-//
-bool Connection::abort(bool keepReplyPort)
-{
-       StLock<Mutex> _(lock);
-    if (!keepReplyPort)
-        mClientPort.destroy();         // dead as a doornail already
-       switch (state) {
-       case idle:
-               secdebug("SS", "Connection %p aborted", this);
-               return true;                            // just shoot me
-       case busy:
-               state = dying;                          // shoot me soon, please
-               if (agentWait)
-                       agentWait->cancel();
-               secdebug("SS", "Connection %p abort deferred (busy)", this);
-               return false;                           // but not quite yet
-       default:
-               assert(false);                          // impossible (we hope)
-               return true;                            // placebo
-       }
-}
-
-
-//
-// Service request framing.
-// These are here so "hanging" connection service threads don't fall
-// into the Big Bad Void as Connections and processes drop out from
-// under them.
-//
-void Connection::beginWork()
-{
-       switch (state) {
-       case idle:
-               state = busy;
-               process.beginConnection(*this);
-               break;
-       case busy:
-               secdebug("SS", "Attempt to re-enter connection %p(port %d)", this, mClientPort.port());
-               CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);        //@@@ some state-error code instead?
-       default:
-               assert(false);
-       }
-}
-
-void Connection::checkWork()
-{
-       StLock<Mutex> _(lock);
-       switch (state) {
-       case busy:
-               return;
-       case dying:
-               agentWait = NULL;       // obviously we're not waiting on this
-               throw this;
-       default:
-               assert(false);
-       }
-}
-
-bool Connection::endWork()
-{
-       switch (state) {
-       case busy:
-               // process the n-step aclUpdateTrigger
-               if (aclUpdateTrigger) {
-            if (--aclUpdateTriggerCount == 0) {
-                aclUpdateTrigger = NULL;
-                secdebug("kcacl", "acl update trigger expires");
-            } else
-                secdebug("kcacl", "acl update trigger armed for %d calls",
-                    aclUpdateTriggerCount);
-        }
-               // end involvement
-               state = idle;
-               process.endConnection(*this);
-               return false;
-       case dying:
-               secdebug("SS", "Connection %p abort resuming", this);
-               if (process.endConnection(*this))
-                       delete &process;
-               return true;
-       default:
-               assert(false);
-               return true;    // placebo
-       }
-}
-
-
-//
-// Key creation and release
-//
-void Connection::releaseKey(Key::Handle key)
-{
-       delete &Server::key(key);
-}
-
-
-//
-// Key inquiries
-//
-CSSM_KEY_SIZE Connection::queryKeySize(Key &key)
-{
-    CssmClient::Key theKey(Server::csp(), key);
-    return theKey.sizeInBits();
-}
-
-
-//
-// Signatures and MACs
-//
-void Connection::generateSignature(const Context &context, Key &key,
-       CSSM_ALGORITHMS signOnlyAlgorithm, const CssmData &data, CssmData &signature)
-{
-       context.replace(CSSM_ATTRIBUTE_KEY, key.cssmKey());
-       key.validate(CSSM_ACL_AUTHORIZATION_SIGN, context);
-       CssmClient::Sign signer(Server::csp(), context.algorithm(), signOnlyAlgorithm);
-       signer.override(context);
-       signer.sign(data, signature);
-}
-
-void Connection::verifySignature(const Context &context, Key &key,
-       CSSM_ALGORITHMS verifyOnlyAlgorithm, const CssmData &data, const CssmData &signature)
-{
-       context.replace(CSSM_ATTRIBUTE_KEY, key.cssmKey());
-       CssmClient::Verify verifier(Server::csp(), context.algorithm(), verifyOnlyAlgorithm);
-       verifier.override(context);
-       verifier.verify(data, signature);
-}
-
-void Connection::generateMac(const Context &context, Key &key,
-       const CssmData &data, CssmData &mac)
-{
-       context.replace(CSSM_ATTRIBUTE_KEY, key.cssmKey());
-       key.validate(CSSM_ACL_AUTHORIZATION_MAC, context);
-       CssmClient::GenerateMac signer(Server::csp(), context.algorithm());
-       signer.override(context);
-       signer.sign(data, mac);
-}
-
-void Connection::verifyMac(const Context &context, Key &key,
-       const CssmData &data, const CssmData &mac)
-{
-       context.replace(CSSM_ATTRIBUTE_KEY, key.cssmKey());
-       key.validate(CSSM_ACL_AUTHORIZATION_MAC, context);
-       CssmClient::VerifyMac verifier(Server::csp(), context.algorithm());
-       verifier.override(context);
-       verifier.verify(data, mac);
-}
-
-
-//
-// Encryption/decryption
-//
-void Connection::encrypt(const Context &context, Key &key,
-       const CssmData &clear, CssmData &cipher)
-{
-       context.replace(CSSM_ATTRIBUTE_KEY, key.cssmKey());
-       key.validate(CSSM_ACL_AUTHORIZATION_ENCRYPT, context);
-       CssmClient::Encrypt cryptor(Server::csp(), context.algorithm());
-       cryptor.override(context);
-       CssmData remData;
-       size_t totalLength = cryptor.encrypt(clear, cipher, remData);
-       // shouldn't need remData - if an algorithm REQUIRES this, we'd have to ship it
-       if (remData)
-               CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
-       cipher.length(totalLength);
-}
-
-void Connection::decrypt(const Context &context, Key &key,
-       const CssmData &cipher, CssmData &clear)
-{
-       context.replace(CSSM_ATTRIBUTE_KEY, key.cssmKey());
-       key.validate(CSSM_ACL_AUTHORIZATION_DECRYPT, context);
-       CssmClient::Decrypt cryptor(Server::csp(), context.algorithm());
-       cryptor.override(context);
-       CssmData remData;
-       size_t totalLength = cryptor.decrypt(cipher, clear, remData);
-       // shouldn't need remData - if an algorithm REQUIRES this, we'd have to ship it
-       if (remData)
-               CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
-       clear.length(totalLength);
-}
-
-
-//
-// Key generation and derivation.
-// Currently, we consider symmetric key generation to be fast, but
-// asymmetric key generation to be (potentially) slow.
-//
-void Connection::generateKey(Database *db, const Context &context,
-               const AccessCredentials *cred, const AclEntryPrototype *owner,
-               uint32 usage, uint32 attrs, Key * &newKey)
-{
-       // prepare a context
-       CssmClient::GenerateKey generate(Server::csp(), context.algorithm());
-       generate.override(context);
-       
-       // generate key
-       // @@@ turn "none" return into reference if permanent (only)
-       CssmKey key;
-       generate(key, Key::KeySpec(usage, attrs));
-               
-       // register and return the generated key
-    newKey = new Key(db, key, attrs & Key::managedAttributes, owner);
-}
-
-void Connection::generateKey(Database *db, const Context &context,
-       const AccessCredentials *cred, const AclEntryPrototype *owner,
-       uint32 pubUsage, uint32 pubAttrs, uint32 privUsage, uint32 privAttrs,
-    Key * &publicKey, Key * &privateKey)
-{
-       // prepare a context
-       CssmClient::GenerateKey generate(Server::csp(), context.algorithm());
-       generate.override(context);
-       
-       // this may take a while; let our server object know
-       Server::active().longTermActivity();
-       
-       // generate keys
-       // @@@ turn "none" return into reference if permanent (only)
-       CssmKey pubKey, privKey;
-       generate(pubKey, Key::KeySpec(pubUsage, pubAttrs),
-               privKey, Key::KeySpec(privUsage, privAttrs));
-               
-       // register and return the generated keys
-       publicKey = new Key(db, pubKey, pubAttrs & Key::managedAttributes, owner);
-       privateKey = new Key(db, privKey, privAttrs & Key::managedAttributes, owner);
-}
-
-Key &Connection::deriveKey(Database *db, const Context &context, Key *baseKey,
-               const AccessCredentials *cred, const AclEntryPrototype *owner,
-        CssmData *param, uint32 usage, uint32 attrs)
-{
-       // prepare a key-derivation context
-    if (baseKey) {
-               baseKey->validate(CSSM_ACL_AUTHORIZATION_DERIVE, cred);
-        context.replace(CSSM_ATTRIBUTE_KEY, baseKey->cssmKey());
-       }
-       CssmClient::DeriveKey derive(Server::csp(), context.algorithm(), CSSM_ALGID_NONE);
-       derive.override(context);
-       
-       // derive key
-       // @@@ turn "none" return into reference if permanent (only)
-       CssmKey key;
-       derive(param, Key::KeySpec(usage, attrs), key);
-               
-       // register and return the generated key
-    return *new Key(db, key, attrs & Key::managedAttributes, owner);
-}
-
-
-//
-// Key wrapping and unwrapping.
-// Note that the key argument (the key in the context) is optional because of the special
-// case of "cleartext" (null algorithm) wrapping for import/export.
-//
-
-void Connection::wrapKey(const Context &context, Key *key,
-    Key &keyToBeWrapped, const AccessCredentials *cred,
-    const CssmData &descriptiveData, CssmKey &wrappedKey)
-{
-    keyToBeWrapped.validate(context.algorithm() == CSSM_ALGID_NONE ?
-            CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR : CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED,
-        cred);
-       if(!(keyToBeWrapped.attributes() & CSSM_KEYATTR_EXTRACTABLE)) {
-               CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK);
-       }
-    if (key)
-        context.replace(CSSM_ATTRIBUTE_KEY, key->cssmKey());
-    CssmClient::WrapKey wrap(Server::csp(), context.algorithm());
-    wrap.override(context);
-    wrap.cred(const_cast<AccessCredentials *>(cred));  //@@@ const madness - fix in client/pod
-    wrap(keyToBeWrapped, wrappedKey, &descriptiveData);
-}
-
-Key &Connection::unwrapKey(Database *db, const Context &context, Key *key,
-       const AccessCredentials *cred, const AclEntryPrototype *owner,
-       uint32 usage, uint32 attrs, const CssmKey wrappedKey,
-    Key *publicKey, CssmData *descriptiveData)
-{
-    if (key)
-        context.replace(CSSM_ATTRIBUTE_KEY, key->cssmKey());
-    CssmClient::UnwrapKey unwrap(Server::csp(), context.algorithm());
-    unwrap.override(context);
-    CssmKey unwrappedKey;
-    unwrap.cred(const_cast<AccessCredentials *>(cred));        //@@@ const madness - fix in client/pod
-    if (owner) {
-        AclEntryInput ownerInput(*owner);      //@@@ const trouble - fix in client/pod
-        unwrap.aclEntry(ownerInput);
-    }
-
-    // @@@ Invoking conversion operator to CssmKey & on *publicKey and take the address of the result.
-    unwrap(wrappedKey, Key::KeySpec(usage, attrs), unwrappedKey,
-        descriptiveData, publicKey ? &static_cast<const CssmKey &>(*publicKey) : NULL);
-
-    return *new Key(db, unwrappedKey, attrs & Key::managedAttributes, owner);
-}
-
-
-//
-// Miscellaneous CSSM functions
-//
-uint32 Connection::getOutputSize(const Context &context, Key &key, uint32 inputSize, bool encrypt)
-{
-    // We're fudging here somewhat, since the context can be any type.
-    // ctx.override will fix the type, and no-one's the wiser.
-       context.replace(CSSM_ATTRIBUTE_KEY, key.cssmKey());
-    CssmClient::Digest ctx(Server::csp(), context.algorithm());
-    ctx.override(context);
-    return ctx.getOutputSize(inputSize, encrypt);
-}
-