#include "ccs_common.h"
#include <syslog.h>
#include <DiskArbitration/DiskArbitration.h>
#include <DiskArbitration/DiskArbitrationPrivate.h>
#include <dispatch/dispatch.h>
#include <bsm/libbsm.h>
#include "k5_mig_server.h"
#include "ccs_os_server.h"
static char *
cf2cstring(CFStringRef inString)
{
char *string = NULL;
CFIndex length;
string = (char *) CFStringGetCStringPtr (inString, kCFStringEncodingUTF8);
if (string)
return strdup(string);
length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(inString),
kCFStringEncodingUTF8) + 1;
string = malloc (length);
if (string == NULL)
return NULL;
if (!CFStringGetCString (inString, string, length, kCFStringEncodingUTF8)) {
free (string);
return NULL;
}
return string;
}
static void
callback(DADiskRef disk, void *context)
{
CFStringRef path, ident;
CFURLRef url;
CFDictionaryRef dict;
size_t len;
char *str, *str2;
dict = DADiskCopyDescription(disk);
if (dict == NULL)
return;
url = (CFURLRef)CFDictionaryGetValue(dict, kDADiskDescriptionVolumePathKey);
if (url == NULL)
goto out;
path = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
if (path == NULL)
goto out;
str = cf2cstring(path);
CFRelease(path);
if (str == NULL)
goto out;
len = strlen(str);
if (len > 0 && str[len - 1] == '/')
len--;
asprintf(&str2, "fs:%.*s", (int)len, str);
free(str);
ident = CFStringCreateWithCString(NULL, str2, kCFStringEncodingUTF8);
free(str2);
if (ident) {
KRBCredFindByLabelAndRelease(ident);
CFRelease(ident);
}
out:
CFRelease(dict);
}
static void
listen_unmount(void)
{
DASessionRef session = DASessionCreate(kCFAllocatorDefault);
dispatch_queue_t queue;
queue = dispatch_queue_create("com.apple.CCacheServer.diskwatch", NULL);
DASessionSetDispatchQueue(session, queue);
DARegisterDiskDisappearedCallback(session, NULL, callback, NULL);
}
int32_t k5_ipc_server_add_client (mach_port_t in_client_port)
{
return cci_check_error (ccs_server_add_client (in_client_port));
}
int32_t k5_ipc_server_remove_client (mach_port_t in_client_port)
{
return cci_check_error (ccs_server_remove_client (in_client_port));
}
kern_return_t k5_ipc_server_handle_request (mach_port_t in_connection_port,
audit_token_t remote_creds,
mach_port_t in_reply_port,
k5_ipc_stream in_request_stream)
{
au_asid_t mAuditSessionId;
audit_token_to_au32(remote_creds, NULL, NULL, NULL, NULL, NULL,
NULL, &mAuditSessionId, NULL);
return cci_check_error (ccs_server_handle_request (in_connection_port,
mAuditSessionId,
in_reply_port,
in_request_stream));
}
#pragma mark -
cc_int32 ccs_os_server_initialize (int argc, const char *argv[])
{
openlog (argv[0], LOG_CONS | LOG_PID, LOG_AUTH);
syslog (LOG_INFO, "Starting up.");
#define CCS_TIMEOUT (600ULL * NSEC_PER_SEC)
dispatch_source_timer_create(DISPATCH_TIMER_INTERVAL,
CCS_TIMEOUT, NSEC_PER_SEC, NULL,
dispatch_get_main_queue(),
^(dispatch_event_t event) {
cc_int32 err = 0;
int valid = 0;
err = ccs_server_valid(&valid);
if (!err && !valid && ccs_server_isrefed() == 0) {
syslog(LOG_NOTICE, "No valid tickets, timing out");
exit(0);
}
}
);
listen_unmount();
return cci_check_error (ccNoError);
}
cc_int32 ccs_os_server_cleanup (int argc, const char *argv[])
{
cc_int32 err = 0;
syslog (LOG_NOTICE, "Exiting.");
return cci_check_error (err);
}
cc_int32 ccs_os_server_listen_loop (int argc, const char *argv[])
{
k5_ipc_server_listen();
dispatch_main();
}
cc_int32 ccs_os_server_send_reply (ccs_pipe_t in_reply_pipe,
k5_ipc_stream in_reply_stream)
{
return cci_check_error (k5_ipc_server_send_reply (in_reply_pipe,
in_reply_stream));
}