#include <mach/mach.h>
#include <mach/mach_error.h>
#include <servers/bootstrap.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <sys/errno.h>
#include <asl.h>
#include <stdio.h>
#include <netsmb/smb.h>
#include <fs/smbfs/smbfs.h>
#include "load_smbfs.h"
#include "smbfs_load_kext.h"
#include "smbfs_load_kextServer.h"
#define CFENVFORMATSTRING "__CF_USER_TEXT_ENCODING=0x%X:0:0"
union MaxMsgSize {
union __RequestUnion__smbfs_load_kext_subsystem req;
union __ReplyUnion__smbfs_load_kext_subsystem rep;
};
static int LoadKext(const char *inKextPath)
{
pid_t childPID;
int status = 0;
if ((childPID = vfork()) < 0)
return errno;
if (childPID == 0) {
char CFUserTextEncodingEnvSetting[sizeof(CFENVFORMATSTRING) + 20];
const char *env[] = {CFUserTextEncodingEnvSetting, "", NULL };
snprintf(CFUserTextEncodingEnvSetting, sizeof(CFUserTextEncodingEnvSetting), CFENVFORMATSTRING, getuid());
execle(KEXT_LOAD_PATH, KEXT_LOAD_PATH, "-q", inKextPath, NULL, env);
_exit(errno);
}
else
waitpid(childPID, &status, 0);
if(WIFEXITED(status))
return WEXITSTATUS(status);
else if(WIFSIGNALED(status))
return WTERMSIG(status);
else
return EIO;
}
kern_return_t do_load_kext(mach_port_t test_port __attribute__((unused)), string_t kextname)
{
int error = KERN_SUCCESS;
struct vfsconf vfc;
if(geteuid() != 0)
{
asl_log(NULL, NULL, ASL_LEVEL_ERR, "Need to be root to load kext euid = %d!\n", geteuid());
return EACCES;
}
if (strcmp(kextname, SMBFS_VFSNAME) == 0) {
if (getvfsbyname(SMBFS_VFSNAME, &vfc) != 0)
error = LoadKext(SMB_KEXT_PATH);
} else
error = ENOENT;
return error;
}
static mach_port_t checkin_or_register(const char *bname)
{
kern_return_t kr;
mach_port_t mp;
kr = bootstrap_check_in(bootstrap_port, (char *)bname, &mp);
if (kr == KERN_SUCCESS)
return mp;
exit(EXIT_FAILURE);
}
int main(void)
{
mach_msg_size_t mxmsgsz = (mach_msg_size_t)(sizeof(union MaxMsgSize) + MAX_TRAILER_SIZE);
mach_port_t mp = checkin_or_register(SMBFS_LOAD_KEXT_BOOTSTRAP_NAME);
kern_return_t kr;
kr = mach_msg_server_once(smbfs_load_kext_server, mxmsgsz, mp, 0);
if (kr != KERN_SUCCESS) {
asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "mach_msg_server(mp): %s\n", mach_error_string(kr));
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}