]> git.saurik.com Git - apple/security.git/blobdiff - SecurityServer/server.cpp
Security-222.tar.gz
[apple/security.git] / SecurityServer / server.cpp
diff --git a/SecurityServer/server.cpp b/SecurityServer/server.cpp
deleted file mode 100644 (file)
index a26998b..0000000
+++ /dev/null
@@ -1,347 +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.
- */
-
-
-//
-// server - the actual SecurityServer server object
-//
-#include "server.h"
-#include "session.h"
-#include "acls.h"
-#include "notifications.h"
-#include "ucsp.h"
-#include <mach/mach_error.h>
-#include <bsm/audit.h>
-#include <bsm/audit_kevents.h>
-#include <bsm/audit_record.h>
-#include <bsm/audit_uevents.h>
-#include <bsm/libbsm.h>
-#include "ccaudit.h"
-
-using namespace MachPlusPlus;
-
-//
-// Construct the server object
-//
-Server::Server(Authority &authority, CodeSignatures &signatures, const char *bootstrapName)
-  : MachServer(bootstrapName),
-    mBootstrapName(bootstrapName),
-    mCurrentConnection(false),
-    mCSPModule(gGuidAppleCSP, mCssm), mCSP(mCSPModule),
-    mAuthority(authority),
-       mCodeSignatures(signatures)
-{
-
-    initAudit();
-
-    // engage the subsidiary port handler for sleep notifications
-    add(sleepWatcher);
-}
-
-
-//
-// Clean up the server object
-//
-Server::~Server()
-{
-    //@@@ more later
-}
-
-
-//
-// Locate a connection by reply port and make it the current connection
-// of this thread. The connection will be marked busy, and can be accessed
-// by calling Server::connection() [no argument] until it is released by
-// calling Connection::endWork().
-//
-Connection &Server::connection(mach_port_t port)
-{
-       Server &server = active();
-       StLock<Mutex> _(server.lock);
-       ConnectionMap::iterator it = server.connections.find(port);
-       if (it == server.connections.end()) // unknown client port -- could be a hack attempt
-               CssmError::throwMe(CSSM_ERRCODE_INVALID_CONTEXT_HANDLE);
-       Connection *conn = it->second;
-       active().mCurrentConnection = conn;
-       conn->beginWork();
-       return *conn;
-}
-
-Connection &Server::connection(bool tolerant)
-{
-       Connection *conn = active().mCurrentConnection;
-       assert(conn);   // have to have one
-       if (!tolerant)
-               conn->checkWork();
-       return *conn;
-}
-
-void Server::requestComplete()
-{
-       // note: there may not be an active connection if connection setup failed
-       if (Connection *conn = active().mCurrentConnection) {
-               if (conn->endWork())
-                       delete conn;
-               active().mCurrentConnection = NULL;
-       }
-}
-
-
-//
-// Locate an ACL bearer (database or key) by handle
-//
-SecurityServerAcl &Server::aclBearer(AclKind kind, CSSM_HANDLE handle)
-{
-       SecurityServerAcl &bearer = findHandle<SecurityServerAcl>(handle);
-       if (kind != bearer.kind())
-               CssmError::throwMe(CSSMERR_CSSM_INVALID_HANDLE_USAGE);
-       return bearer;
-}
-
-
-//
-// Run the server. This will not return until the server is forced to exit.
-//
-void Server::run()
-{
-       MachServer::run(0x10000,
-        MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0) |
-        MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT));
-}
-
-
-//
-// The primary server run-loop function.
-// Invokes the MIG-generated main dispatch function (ucsp_server).
-// For debug builds, look up request names in a MIG-generated table
-// for better debug-log messages.
-//
-boolean_t ucsp_server(mach_msg_header_t *, mach_msg_header_t *);
-
-#if defined(NDEBUG)
-
-boolean_t Server::handle(mach_msg_header_t *in, mach_msg_header_t *out)
-{
-       return ucsp_server(in, out);
-}
-
-#else //NDEBUG
-
-static const struct IPCName { const char *name; int ipc; } ipcNames[] =
-    { subsystem_to_name_map_ucsp };    // macro generated by MIG, from ucsp.h
-
-boolean_t Server::handle(mach_msg_header_t *in, mach_msg_header_t *out)
-{
-    const int first = ipcNames[0].ipc;
-    const char *name = (in->msgh_id >= first && in->msgh_id < first + ucsp_MSG_COUNT) ?
-               ipcNames[in->msgh_id - first].name : "OUT OF BOUNDS";
-    secdebug("SSreq", "begin %s (%d)", name, in->msgh_id);
-       boolean_t result = ucsp_server(in, out);
-    secdebug("SSreq", "end %s (%d)", name, in->msgh_id);
-    return result;
-}
-
-#endif //NDEBUG
-
-
-//
-// Set up a new Connection. This establishes the environment (process et al) as needed
-// and registers a properly initialized Connection object to run with.
-// Type indicates how "deep" we need to initialize (new session, process, or connection).
-// Everything at and below that level is constructed. This is straight-forward except
-// in the case of session re-initialization (see below).
-//
-// audit_token_t.val[1] is the EUID, audit_token_t.val[2] is the EGID.  
-//
-void Server::setupConnection(ConnectLevel type, Port servicePort, Port replyPort, Port taskPort,
-    const audit_token_t &auditToken, 
-    const ClientSetupInfo *info, const char *identity)
-{
-       // first, make or find the process based on task port
-       StLock<Mutex> _(lock);
-       Process * &proc = processes[taskPort];
-       if (type == connectNewSession && proc) {
-               // The client has talked to us before and now wants to create a new session.
-               // We'll unmoor the old process object and cast it adrift (it will die either now
-               // or later following the usual deferred-death mechanics).
-               // The connection object will die (it's probably already dead) because the client
-               // has destroyed its replyPort. So we don't worry about this here.
-               secdebug("server", "session setup - marooning old process %p(%d) of session %p",
-                       proc, proc->pid(), &proc->session);
-               if (proc->kill(true))
-                       delete proc;
-               proc = NULL;
-       }
-       if (!proc) {
-               if (type == connectNewThread)   // client error (or attack)
-                       CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
-               assert(info && identity);
-               proc = new Process(servicePort, taskPort, info, identity,
-                       auditToken.val[1], auditToken.val[2]);
-               notifyIfDead(taskPort);
-       }
-
-       // now, establish a connection and register it in the server
-       Connection *connection = new Connection(*proc, replyPort);
-       if (connections[replyPort])     // malicious re-entry attempt?
-               CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);        //@@@ error code? (client error)
-       connections[replyPort] = connection;
-       notifyIfDead(replyPort);
-}
-
-
-//
-// Synchronously end a Connection.
-// This is due to a request from the client, so no thread races are possible.
-//
-void Server::endConnection(Port replyPort)
-{
-       StLock<Mutex> _(lock);
-       Connection *connection = connections[replyPort];
-       assert(connection);
-       connections.erase(replyPort);
-       connection->terminate();
-       delete connection;
-}
-
-
-//
-// Handling dead-port notifications.
-// This receives DPNs for all kinds of ports we're interested in.
-//
-void Server::notifyDeadName(Port port)
-{
-       StLock<Mutex> _(lock);
-       secdebug("SSports", "port %d is dead", port.port());
-    
-    // is it a connection?
-    ConnectionMap::iterator conIt = connections.find(port);
-    if (conIt != connections.end()) {
-        Connection *connection = conIt->second;
-               if (connection->abort())
-                       delete connection;
-               connections.erase(conIt);
-        return;
-    }
-    
-    // is it a process?
-    ProcessMap::iterator procIt = processes.find(port);
-    if (procIt != processes.end()) {
-        Process *process = procIt->second;
-               if (process->kill())
-                       delete process;
-               processes.erase(procIt);
-        return;
-    }
-    
-    // is it a notification client?
-    if (Listener::remove(port))
-        return;
-    
-       secdebug("server", "spurious dead port notification for port %d", port.port());
-}
-
-
-//
-// Handling no-senders notifications.
-// This is currently only used for (subsidiary) service ports
-//
-void Server::notifyNoSenders(Port port, mach_port_mscount_t)
-{
-       secdebug("SSports", "port %d no senders", port.port());
-       Session::eliminate(port);
-}
-
-
-//
-// Notifier for system sleep events
-//
-void Server::SleepWatcher::systemWillSleep()
-{
-    secdebug("SS", "sleep notification received");
-    Session::lockAllDatabases(true);
-}
-
-void Server::initAudit(void)
-{
-    secdebug("SS", "initializing Common Criteria auditing");
-    mAudit.auditId(geteuid());
-    // Set the class mask so only the audit records we submit are written.
-    mAudit.eventMask().set(AUE_NULL, AUE_NULL);
-       mAudit.terminalId().set();
-    // XXX  If we use SS session IDs instead, get the RootSession ID
-    mAudit.sessionId(getpid());
-       mAudit.registerSession();
-}
-
-//
-// Return the primary Cryptographic Service Provider.
-// This will be lazily loaded when it is first requested.
-//
-CssmClient::CSP &Server::getCsp()
-{
-    if (!mCssm->isActive())
-               loadCssm();
-    return mCSP;
-}
-
-
-//
-// Initialize the CSSM/MDS subsystem.
-// This is thread-safe and can be done lazily.
-//
-static void initMds();
-
-void Server::loadCssm()
-{
-       if (!mCssm->isActive()) {
-               StLock<Mutex> _(lock);
-               if (!mCssm->isActive()) {
-                       try {
-                               initMds();
-                       } catch (const CssmError &error) {
-                               switch (error.cssmError()) {
-                               case CSSMERR_DL_MDS_ERROR:
-                               case CSSMERR_DL_OS_ACCESS_DENIED:
-                                       secdebug("SS", "MDS initialization failed; continuing");
-                                       Syslog::warning("MDS initialization failed; continuing");
-                                       break;
-                               default:
-                                       throw;
-                               }
-                       }
-                       secdebug("SS", "CSSM initializing");
-                       mCssm->init();
-                       mCSP->attach();
-                       IFDEBUG(char guids[Guid::stringRepLength+1]);
-                       secdebug("SS", "CSSM ready with CSP %s", mCSP->guid().toString(guids));
-               }
-       }
-}
-
-#include <Security/mds.h>
-
-static void initMds()
-{
-       secdebug("SS", "MDS initializing");
-       CssmAllocatorMemoryFunctions memory(CssmAllocator::standard());
-       MDS_FUNCS functions;
-       MDS_HANDLE handle;
-       CssmError::check(MDS_Initialize(NULL, &memory, &functions, &handle));
-       CssmError::check(MDS_Install(handle));
-       CssmError::check(MDS_Terminate(handle));
-}