-//
-// NOSA support functions. This is a test mode where the SecurityAgent
-// is simulated via stdio in the client. Good for running automated tests
-// of client programs. Only available if -DNOSA when compiling.
-//
-#if defined(NOSA)
-
-#include <cstdarg>
-
-static void getNoSA(char *buffer, size_t bufferSize, const char *fmt, ...)
-{
- // write prompt
- va_list args;
- va_start(args, fmt);
- vfprintf(stdout, fmt, args);
- va_end(args);
-
- // read reply
- memset(buffer, 0, bufferSize);
- const char *nosa = getenv("NOSA");
- if (!strcmp(nosa, "-")) {
- if (fgets(buffer, bufferSize-1, stdin) == NULL)
- CssmError::throwMe(CSSM_ERRCODE_NO_USER_INTERACTION);
- buffer[strlen(buffer)-1] = '\0'; // remove trailing newline
- if (!isatty(fileno(stdin)))
- printf("%s\n", buffer); // echo to output if input not terminal
- } else {
- strncpy(buffer, nosa, bufferSize-1);
- printf("%s\n", buffer);
- }
- if (buffer[0] == '\0') // empty input -> cancellation
- CssmError::throwMe(CSSM_ERRCODE_USER_CANCELED);
-}
-
-#endif //NOSA
-
-
-// SecurityAgentConnection
-
-SecurityAgentConnection::SecurityAgentConnection(const AuthHostType type, Session &session)
-: mAuthHostType(type),
-mHostInstance(session.authhost(mAuthHostType)),
-mConnection(&Server::connection()),
-mAuditToken(Server::connection().auditToken())
-{
- // this may take a while
- Server::active().longTermActivity();
- secdebug("SecurityAgentConnection", "new SecurityAgentConnection(%p)", this);
-}
-
-SecurityAgentConnection::~SecurityAgentConnection()
-{
- secdebug("SecurityAgentConnection", "SecurityAgentConnection(%p) dying", this);
- mConnection->useAgent(NULL);
-}
-
-void
-SecurityAgentConnection::activate()
-{
- secdebug("SecurityAgentConnection", "activate(%p)", this);
-
- Session &session = mHostInstance->session();
- SessionId targetSessionId = session.sessionId();
- MachPlusPlus::Bootstrap processBootstrap = Server::process().taskPort().bootstrap();
- fileport_t userPrefsFP = MACH_PORT_NULL;
-
- // send the the userPrefs to SecurityAgent
- if (mAuthHostType == securityAgent || mAuthHostType == userAuthHost) {
- CFRef<CFDataRef> userPrefs(mHostInstance->session().copyUserPrefs());
- if (0 != userPrefs)
- {
- FILE *mbox = NULL;
- int fd = 0;
- mbox = tmpfile();
- if (NULL != mbox)
- {
- fd = dup(fileno(mbox));
- fclose(mbox);
- if (fd != -1)
- {
- CFIndex length = CFDataGetLength(userPrefs);
- if (write(fd, CFDataGetBytePtr(userPrefs), length) != length)
- Syslog::error("could not write userPrefs");
- else
- {
- if (0 == fileport_makeport(fd, &userPrefsFP))
- secdebug("SecurityAgentConnection", "stashed the userPrefs file descriptor");
- else
- Syslog::error("failed to stash the userPrefs file descriptor");
- }
- close(fd);
- }
- }
- }
- if (MACH_PORT_NULL == userPrefsFP)
- {
- secdebug("SecurityAgentConnection", "could not read userPrefs");
- }
- }
-
- mConnection->useAgent(this);
- try
- {
- StLock<Mutex> _(*mHostInstance);
-
- mach_port_t lookupPort = mHostInstance->lookup(targetSessionId);
- if (MACH_PORT_NULL == lookupPort)
- {
- Syslog::error("could not find real service, bailing");
- MacOSError::throwMe(CSSM_ERRCODE_SERVICE_NOT_AVAILABLE);
- }
- // reset Client contact info
- mPort = lookupPort;
- SecurityAgent::Client::activate(mPort);
-
- secdebug("SecurityAgentConnection", "%p activated", this);
- }
- catch (MacOSError &err)
- {
- mConnection->useAgent(NULL); // guess not
- Syslog::error("SecurityAgentConnection: error activating %s instance %p",
- mAuthHostType == privilegedAuthHost
- ? "authorizationhost"
- : "SecurityAgent", this);
- throw;
- }
-
- secdebug("SecurityAgentConnection", "contacting service (%p)", this);
- mach_port_name_t jobPort;
- if (0 > audit_session_port(session.sessionId(), &jobPort))
- Syslog::error("audit_session_port failed: %m");
- MacOSError::check(SecurityAgent::Client::contact(jobPort, processBootstrap, userPrefsFP));
- secdebug("SecurityAgentConnection", "contact didn't throw (%p)", this);
-
- if (userPrefsFP != MACH_PORT_NULL)
- mach_port_deallocate(mach_task_self(), userPrefsFP);
-}
-
-void
-SecurityAgentConnection::reconnect()
-{
- // if !mHostInstance throw()?
- if (mHostInstance)
- {
- activate();
- }
-}
-
-void
-SecurityAgentConnection::terminate()
-{
- activate();
-
- // @@@ This happens already in the destructor; presumably we do this to tear things down orderly
- mConnection->useAgent(NULL);
-}
-