1/*
2 *  Copyright (c) 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// server - master server loop for tokend
25//
26#include "server.h"
27#include "tdclient.h"
28#include <securityd_client/ssclient.h>
29#include <security_cdsa_client/mdsclient.h>
30
31using namespace MachPlusPlus;
32
33
34//
35// The MIG-generated server dispatch function
36//
37extern boolean_t tokend_server(mach_msg_header_t *in, mach_msg_header_t *out);
38
39
40namespace Security {
41namespace Tokend {
42
43
44//
45// The server singleton
46//
47Server *server = NULL;
48
49
50//
51// Drive the server
52//
53int Server::operator () (int argc, const char *argv[], SecTokendCallbackFlags flags)
54{
55	// process command-line arguments as sent by securityd
56	if (argc != 4) {
57		secdebug("tokenlib", "invalid argument count (%d)", argc);
58		Syslog::notice("token daemon invoked with invalid arguments");
59		return 2;
60	}
61
62	// argv[1] == version of wire protocol
63	const char *versionString = argv[1];
64	if (atol(versionString) != TDPROTOVERSION) {
65		// This would be a mismatch between securityd and the SecurityTokend.framework
66		// It's NOT a "binary compatibility" mismatch; that got checked for by our caller.
67		secdebug("tokenlib", "incoming protocol %s expected %d - aborting",
68			versionString, TDPROTOVERSION);
69		return 2;
70	}
71
72	// argv[2] == reader name
73	mReaderName = argv[2];
74	secdebug("tokenlib", "reader '%s' wire protocol %s", mReaderName, versionString);
75
76	// argv[3] == hex coding of reader state, with name() undefined
77	CssmData::wrap(mStartupReaderState).fromHex(argv[3]);
78	mStartupReaderState.name(readerName());	// fix name pointer (shipped separately)
79
80#if !defined(NDEBUG)
81	// stop right here; do not run the server. We're being run from the command line
82	if (flags & kSecTokendCallbacksTestNoServer)
83		return 0;
84#endif
85
86	// handshake with securityd
87	secdebug("tokenlib", "checking in with securityd");
88	SecurityServer::ClientSession client(Allocator::standard(), Allocator::standard());
89	client.childCheckIn(primaryServicePort(), TaskPort());
90
91	// start dispatch; from here on securityd is driving us
92	secdebug("tokenlib", "starting server loop");
93	run();
94
95	// we don't usually return from run(), but just in case
96	termination(0, 0);
97}
98
99
100//
101// Handle the terminate message
102//
103void Server::termination(uint32 reason, uint32 options)
104{
105	secdebug("tokenlib", "terminate(%d,0x%x) received", reason, options);
106	if (terminate)
107		terminate(reason, options);	// ignore return code
108	exit(0);
109}
110
111
112//
113// MIG handler hook
114//
115boolean_t Server::handle(mach_msg_header_t *in, mach_msg_header_t *out)
116{
117	return tokend_server(in, out);
118}
119
120
121}	// namespace Tokend
122}	// namespace Security
123