#include <CoreFoundation/CoreFoundation.h>
#include <CoreServices/CoreServicesPriv.h>
#include <asl.h>
#include <netsmb/smb_lib.h>
#include <charsets.h>
#include <parse_url.h>
#include <netsmb/smb_conn.h>
#include <NetFS/NetFS.h>
#include <netsmb/netbios.h>
#include <netsmb/nb_lib.h>
#define CIFS_SCHEME_LEN 5
#define SMB_SCHEME_LEN 4
static void LogCFString(CFStringRef theString, const char *debugstr, const char * func, int lineNum)
{
char prntstr[1024];
if (theString == NULL)
return;
CFStringGetCString(theString, prntstr, 1024, kCFStringEncodingUTF8);
smb_log_info("%s-line:%d %s = %s", ASL_LEVEL_DEBUG, func, lineNum, debugstr, prntstr);
}
#ifdef SMB_DEBUG
#define DebugLogCFString LogCFString
#else // SMB_DEBUG
#define DebugLogCFString(theString, debugstr, func, lineNum)
#endif // SMB_DEBUG
int isUrlStringEqual(CFURLRef url1, CFURLRef url2)
{
if ((url1 == NULL) || (url2 == NULL)) {
return FALSE;
}
if (CFStringCompare(CFURLGetString(url1), CFURLGetString(url1),
kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
return TRUE;
}
return FALSE;
}
char *CStringCreateWithCFString(CFStringRef inStr)
{
CFIndex maxLen;
char *str;
maxLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(inStr),
kCFStringEncodingUTF8) + 1;
str = malloc(maxLen);
if (!str) {
smb_log_info("%s malloc failed, syserr = %s", ASL_LEVEL_ERR,
__FUNCTION__,strerror(ENOMEM));
return NULL;
}
CFStringGetCString(inStr, str, maxLen, kCFStringEncodingUTF8);
return str;
}
static int SMBSchemeLength(CFURLRef url)
{
int len = 0;
CFStringRef scheme = CFURLCopyScheme (url);
if (scheme == NULL)
return 0;
if ( kCFCompareEqualTo == CFStringCompare (scheme, CFSTR("smb"), kCFCompareCaseInsensitive) )
len = SMB_SCHEME_LEN;
else if ( kCFCompareEqualTo == CFStringCompare (scheme, CFSTR("cifs"), kCFCompareCaseInsensitive) )
len = CIFS_SCHEME_LEN;
else
len = -1;
CFRelease(scheme);
return len;
}
static void CreateStringByReplacingPercentEscapesUTF8(CFStringRef *inOutStr, CFStringRef LeaveEscaped)
{
CFStringRef inStr = (inOutStr) ? *inOutStr : NULL;
if (!inStr)
return;
*inOutStr = CFURLCreateStringByReplacingPercentEscapesUsingEncoding(NULL, inStr, LeaveEscaped, kCFStringEncodingUTF8);
CFRelease(inStr);
}
static void CreateStringByAddingPercentEscapesUTF8(CFStringRef *inOutStr, CFStringRef leaveUnescaped, CFStringRef toBeEscaped, Boolean doRelease)
{
CFStringRef inStr = (inOutStr) ? *inOutStr : NULL;
if (!inStr)
return;
*inOutStr = CFURLCreateStringByAddingPercentEscapes(NULL, inStr, leaveUnescaped, toBeEscaped, kCFStringEncodingUTF8);
if (doRelease)
CFRelease(inStr);
}
static CFArrayRef CreateWrkgrpUserArrayFromCFStringRef(CFStringRef inString, CFStringRef separatorString)
{
CFArrayRef userArray = NULL;
userArray = CFStringCreateArrayBySeparatingStrings(kCFAllocatorDefault, inString, separatorString);
if (userArray && (CFArrayGetCount(userArray) != 2)) {
CFRelease(userArray);
userArray = NULL;
}
return userArray;
}
static CFArrayRef CreateWrkgrpUserArray(CFURLRef url)
{
CFStringRef netlocation = NULL;
CFArrayRef userArray = NULL;
netlocation = CFURLCopyNetLocation(url);
if (!netlocation)
return NULL;
userArray = CreateWrkgrpUserArrayFromCFStringRef(netlocation, CFSTR(";"));
CFRelease(netlocation);
return userArray;
}
static int SetServerFromURL(struct smb_ctx *ctx, CFURLRef url)
{
CFIndex maxlen;
CFStringRef serverNameRef = CFURLCopyHostName(url);
if (serverNameRef && ctx->serverNameRef && ctx->serverName &&
(ctx->serverIsDomainController) &&
(ctx->ct_flags & SMBCF_CONNECTED) &&
(CFStringCompare(serverNameRef, ctx->serverNameRef, 0) == kCFCompareEqualTo)) {
CFRelease(serverNameRef);
return 0;
}
if (ctx->serverNameRef) {
CFRelease(ctx->serverNameRef);
}
ctx->serverNameRef = serverNameRef;
if (ctx->serverNameRef == NULL)
return EINVAL;
DebugLogCFString(ctx->serverNameRef, "Server", __FUNCTION__, __LINE__);
maxlen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(ctx->serverNameRef), kCFStringEncodingUTF8) + 1;
if (ctx->serverName)
free(ctx->serverName);
ctx->serverName = malloc(maxlen);
if (!ctx->serverName) {
CFRelease(ctx->serverNameRef);
ctx->serverNameRef = NULL;
return ENOMEM;
}
CFStringGetCString(ctx->serverNameRef, ctx->serverName, maxlen, kCFStringEncodingUTF8);
return 0;
}
static CFStringRef CopyUserAndWorkgroupFromURL(CFStringRef *outWorkGroup, CFURLRef url)
{
CFURLRef net_url = NULL;
CFArrayRef userArray = NULL;
CFStringRef userString = NULL;
CFMutableStringRef urlString = NULL;
CFStringRef wrkgrpString = NULL;
*outWorkGroup = NULL;
userArray = CreateWrkgrpUserArray(url);
if (!userArray)
return(CFURLCopyUserName(url));
urlString = CFStringCreateMutableCopy(NULL, 1024, CFSTR("smb://"));
if (!urlString) {
CFRelease(userArray);
return(CFURLCopyUserName(url));
}
CFStringAppend(urlString, (CFStringRef)CFArrayGetValueAtIndex(userArray, 1));
net_url = CFURLCreateWithString(NULL, urlString, NULL);
CFRelease(urlString);
urlString = NULL;
if (!net_url) {
CFRelease(userArray);
return(CFURLCopyUserName(url));
}
userString = CFURLCopyUserName(net_url);
CFRelease(net_url);
wrkgrpString = CFStringCreateCopy(NULL, (CFStringRef)CFArrayGetValueAtIndex(userArray, 0));
CreateStringByReplacingPercentEscapesUTF8(&wrkgrpString, CFSTR(""));
if (wrkgrpString)
*outWorkGroup = wrkgrpString;
CFRelease(userArray);
return(userString);
}
static CFStringRef SetWorkgroupFromURL(struct smb_ctx *ctx, CFURLRef url)
{
CFStringRef userString = NULL;
CFStringRef wrkgrpString = NULL;
userString = CopyUserAndWorkgroupFromURL(&wrkgrpString, url);
if (wrkgrpString) {
LogCFString(wrkgrpString, "Workgroup", __FUNCTION__, __LINE__);
if (CFStringGetLength(wrkgrpString) <= SMB_MAXNetBIOSNAMELEN) {
str_upper(ctx->ct_setup.ioc_domain, sizeof(ctx->ct_setup.ioc_domain), wrkgrpString);
}
CFRelease(wrkgrpString);
}
return(userString);
}
static int SetUserNameFromURL(struct smb_ctx *ctx, CFURLRef url)
{
CFStringRef userNameRef = SetWorkgroupFromURL(ctx, url);
char username[SMB_MAXUSERNAMELEN+1];
int error;
if (! userNameRef)
return 0;
LogCFString(userNameRef, "Username",__FUNCTION__, __LINE__);
if (CFStringGetCString(userNameRef, username, SMB_MAXUSERNAMELEN+1, kCFStringEncodingUTF8) == FALSE) {
error = ENAMETOOLONG;
} else {
error = smb_ctx_setuser(ctx, username);
}
CFRelease(userNameRef);
return error;
}
static int SetPasswordFromURL(struct smb_ctx *ctx, CFURLRef url)
{
CFStringRef passwd = CFURLCopyPassword(url);
if (! passwd)
return 0;
if (CFStringGetLength(passwd) >= SMB_MAXPASSWORDLEN) {
CFRelease(passwd);
return ENAMETOOLONG;
}
CFStringGetCString(passwd, ctx->ct_setup.ioc_password, SMB_MAXPASSWORDLEN, kCFStringEncodingUTF8);
ctx->ct_flags |= SMBCF_EXPLICITPWD;
CFRelease(passwd);
return 0;
}
static void SetPortNumberFromURL(struct smb_ctx *ctx, CFURLRef url)
{
SInt32 port = CFURLGetPortNumber(url);
if (port == -1)
return;
ctx->prefs.tcp_port = port;
ctx->prefs.tryBothPorts = FALSE;
smb_log_info("Setting port number to %d", ASL_LEVEL_DEBUG, ctx->prefs.tcp_port);
}
static int GetShareAndPathFromURL(CFURLRef url, CFStringRef *out_share, CFStringRef *out_path)
{
Boolean isAbsolute;
CFArrayRef userArray = NULL;
CFMutableArrayRef userArrayM = NULL;
CFStringRef share = CFURLCopyStrictPath(url, &isAbsolute);
CFStringRef path = NULL;
*out_share = NULL;
*out_path = NULL;
if (share && (CFStringGetLength(share) == 0)) {
CFRelease(share);
share = NULL;
}
if (!share)
return 0;
userArray = CFStringCreateArrayBySeparatingStrings(NULL, share, CFSTR("/"));
if (userArray && (CFArrayGetCount(userArray) > 1))
userArrayM = CFArrayCreateMutableCopy(NULL, CFArrayGetCount(userArray), userArray);
if (userArray)
CFRelease(userArray);
if (userArrayM) {
CFMutableStringRef newshare;
newshare = CFStringCreateMutableCopy(NULL, 0, (CFStringRef)CFArrayGetValueAtIndex(userArrayM, 0));
if (newshare) {
CFStringTrim(newshare, CFSTR("/"));
CreateStringByReplacingPercentEscapesUTF8((CFStringRef *) &newshare, CFSTR("/"));
}
CFArrayRemoveValueAtIndex(userArrayM, 0);
path = CFStringCreateByCombiningStrings(NULL, userArrayM, CFSTR("/"));
if (path && (CFStringGetLength(path) == 0)) {
CFRelease(path);
path = NULL;
}
if (path) {
CFMutableStringRef newpath = CFStringCreateMutableCopy(NULL, 0, path);
if (newpath) {
CFStringTrim(newpath, CFSTR("/"));
CFRelease(path);
path = newpath;
}
}
if (path) {
CreateStringByReplacingPercentEscapesUTF8(&path, CFSTR("/"));
LogCFString(path, "Path", __FUNCTION__, __LINE__);
}
CFRelease(userArrayM);
if (newshare) {
CFRelease(share);
share = newshare;
}
} else
CreateStringByReplacingPercentEscapesUTF8(&share, CFSTR("/"));
if (share && ( kCFCompareEqualTo == CFStringCompare (share, CFSTR("0x2f"), kCFCompareCaseInsensitive) )) {
CFRelease(share);
share = CFStringCreateCopy(NULL, CFSTR("/"));
}
if (share && (CFStringGetLength(share) >= SMB_MAXSHARENAMELEN)) {
CFRelease(share);
if (path)
CFRelease(path);
return ENAMETOOLONG;
}
*out_share = share;
*out_path = path;
return 0;
}
static int SetShareAndPathFromURL(struct smb_ctx *ctx, CFURLRef url)
{
CFStringRef share = NULL;
CFStringRef path = NULL;
CFIndex maxlen;
int error;
error = GetShareAndPathFromURL(url, &share, &path);
if (error)
return error;
if (!share)
return 0;
DebugLogCFString(share, "Share", __FUNCTION__, __LINE__);
CreateStringByReplacingPercentEscapesUTF8(&share, CFSTR(""));
if (ctx->ct_origshare)
free(ctx->ct_origshare);
if (ctx->mountPath)
CFRelease(ctx->mountPath);
ctx->mountPath = NULL;
maxlen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(share), kCFStringEncodingUTF8) + 1;
ctx->ct_origshare = malloc(maxlen);
if (!ctx->ct_origshare) {
CFRelease(share);
CFRelease(path);
return ENOMEM;
}
CFStringGetCString(share, ctx->ct_origshare, maxlen, kCFStringEncodingUTF8);
str_upper(ctx->ct_sh.ioc_share, sizeof(ctx->ct_sh.ioc_share), share);
CFRelease(share);
ctx->mountPath = path;
return 0;
}
int ParseSMBURL(struct smb_ctx *ctx)
{
int error = EINVAL;
if ((!CFURLCanBeDecomposed(ctx->ct_url)) || (SMBSchemeLength(ctx->ct_url) < 0)) {
smb_log_info("This is an invalid URL, syserr = %s", ASL_LEVEL_ERR,
strerror(error));
return error;
}
error = SetServerFromURL(ctx, ctx->ct_url);
if (error) {
smb_log_info("The URL has a bad server name, syserr = %s", ASL_LEVEL_ERR,
strerror(error));
return error;
}
error = SetUserNameFromURL(ctx, ctx->ct_url);
if (error) {
smb_log_info("The URL has a bad user name, syserr = %s", ASL_LEVEL_ERR,
strerror(error));
return error;
}
error = SetPasswordFromURL(ctx, ctx->ct_url);
if (error) {
smb_log_info("The URL has a bad password, syserr = %s", ASL_LEVEL_ERR,
strerror(error));
return error;
}
SetPortNumberFromURL(ctx, ctx->ct_url);
error = SetShareAndPathFromURL(ctx, ctx->ct_url);
return error;
}
CFURLRef CreateURLFromReferral(CFStringRef inStr)
{
CFURLRef ct_url = NULL;
CFMutableStringRef urlString = CFStringCreateMutableCopy(NULL, 0, CFSTR("smb:/"));
CFStringRef escapeStr = inStr;
CreateStringByAddingPercentEscapesUTF8(&escapeStr, NULL, NULL, FALSE);
if (!escapeStr) {
escapeStr = inStr;
}
if (urlString) {
CFStringAppend(urlString, escapeStr);
ct_url = CFURLCreateWithString(kCFAllocatorDefault, urlString, NULL);
CFRelease(urlString);
}
if (!ct_url) {
LogCFString(inStr, "creating url failed", __FUNCTION__, __LINE__);
}
if (escapeStr != inStr) {
CFRelease(escapeStr);
}
return ct_url;
}
CFURLRef CreateSMBURL(const char *url)
{
CFURLRef ct_url = NULL;
CFStringRef urlString = CFStringCreateWithCString(NULL,
url,
kCFStringEncodingUTF8);
CFStringRef escapedUrlString;
int UNCformat = 0;
escapedUrlString = NULL;
if (urlString && (*url == '\\') && (*(url + 1) == '\\')) {
CFArrayRef urlArray = CFStringCreateArrayBySeparatingStrings(NULL,
urlString,
CFSTR("\\"));
CFRelease(urlString);
urlString = NULL;
if (urlArray) {
urlString = CFStringCreateByCombiningStrings(NULL,
urlArray,
CFSTR("/"));
CFRelease(urlArray);
}
UNCformat = 1;
}
if (!urlString) {
return NULL;
}
DebugLogCFString(urlString, "urlString ", __FUNCTION__, __LINE__);
if ((!CFStringHasPrefix(urlString, CFSTR("smb://"))) &&
(!CFStringHasPrefix(urlString, CFSTR("cifs://")))) {
CFMutableStringRef urlStringM = CFStringCreateMutableCopy(NULL,
1024,
CFSTR("smb:"));
if (urlStringM) {
CFStringAppend(urlStringM, urlString);
CFRelease(urlString);
urlString = urlStringM;
}
}
if (urlString == NULL) {
return (NULL);
}
if (UNCformat == 1) {
escapedUrlString = CFURLCreateStringByAddingPercentEscapes(NULL,
urlString,
NULL,
NULL,
kCFStringEncodingUTF8);
CFRelease(urlString);
if (escapedUrlString == NULL) {
return (NULL);
}
ct_url = CFURLCreateWithString(kCFAllocatorDefault,
escapedUrlString,
NULL);
CFRelease(escapedUrlString);
}
else {
ct_url = CFURLCreateWithString(kCFAllocatorDefault,
urlString,
NULL);
CFRelease(urlString);
}
return ct_url;
}
int smb_url_to_dictionary(CFURLRef url, CFDictionaryRef *dict)
{
CFMutableDictionaryRef mutableDict = NULL;
int error = 0;
CFStringRef Server = NULL;
CFStringRef Username = NULL;
CFStringRef DomainWrkgrp = NULL;
CFStringRef Password = NULL;
CFStringRef Share = NULL;
CFStringRef Path = NULL;
SInt32 PortNumber;
if ((!CFURLCanBeDecomposed(url)) || (SMBSchemeLength(url) < 0)) {
smb_log_info("%s: Invalid URL, syserr = %s", ASL_LEVEL_ERR,
__FUNCTION__, strerror(EINVAL));
goto ErrorOut;
}
mutableDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (mutableDict == NULL) {
error = errno;
smb_log_info("%s: CFDictionaryCreateMutable failed, syserr = %s",
ASL_LEVEL_ERR, __FUNCTION__, strerror(error));
goto ErrorOut;
}
CFDictionarySetValue (mutableDict, kNetFSSchemeKey, CFSTR(SMB_SCHEME_STRING));
Server = CFURLCopyHostName(url);
if (! Server)
goto ErrorOut;
LogCFString(Server, "Server String", __FUNCTION__, __LINE__);
CFDictionarySetValue (mutableDict, kNetFSHostKey, Server);
CFRelease(Server);
Server = NULL;
PortNumber = CFURLGetPortNumber(url);
if (PortNumber != -1) {
CFStringRef tempString = CFStringCreateWithFormat( NULL, NULL, CFSTR( "%d" ), PortNumber );
if (tempString) {
CFDictionarySetValue (mutableDict, kNetFSAlternatePortKey, tempString);
CFRelease(tempString);
}
}
Username = CopyUserAndWorkgroupFromURL(&DomainWrkgrp, url);
LogCFString(Username, "Username String", __FUNCTION__, __LINE__);
LogCFString(DomainWrkgrp, "DomainWrkgrp String", __FUNCTION__, __LINE__);
error = 0;
if ((Username) && (CFStringGetLength(Username) >= SMB_MAXUSERNAMELEN))
error = ENAMETOOLONG;
if ((DomainWrkgrp) && (CFStringGetLength(DomainWrkgrp) > SMB_MAXNetBIOSNAMELEN))
error = ENAMETOOLONG;
if (error) {
if (Username)
CFRelease(Username);
if (DomainWrkgrp)
CFRelease(DomainWrkgrp);
goto ErrorOut;
}
if (DomainWrkgrp && Username && CFStringGetLength(Username)) {
CFMutableStringRef tempString = CFStringCreateMutableCopy(NULL, 0, DomainWrkgrp);
if (tempString) {
CFStringAppend(tempString, CFSTR("\\"));
CFStringAppend(tempString, Username);
CFRelease(Username);
Username = tempString;
}
CFRelease(DomainWrkgrp);
}
if (Username)
{
CFDictionarySetValue (mutableDict, kNetFSUserNameKey, Username);
CFRelease(Username);
}
Password = CFURLCopyPassword(url);
if (Password) {
if (CFStringGetLength(Password) >= SMB_MAXPASSWORDLEN) {
error = ENAMETOOLONG;
CFRelease(Password);
goto ErrorOut;
}
CFDictionarySetValue (mutableDict, kNetFSPasswordKey, Password);
CFRelease(Password);
}
error = GetShareAndPathFromURL(url, &Share, &Path);
if (error)
goto ErrorOut;
LogCFString(Share, "Share String", __FUNCTION__, __LINE__);
LogCFString(Path, "Path String", __FUNCTION__, __LINE__);
if (Share && Path) {
if (CFStringGetLength(Share) == 0) {
CFRelease(Path);
CFRelease(Share);
Share = Path = NULL;
error = EINVAL;
smb_log_info("%s: No share name found, syserr = %s",
ASL_LEVEL_ERR, __FUNCTION__, strerror(error));
goto ErrorOut;
}
if (CFStringGetLength(Path)) {
CFMutableStringRef tempString = CFStringCreateMutableCopy(NULL, 0, Share);
if (tempString) {
CFStringAppend(tempString, CFSTR("/"));
CFStringAppend(tempString, Path);
CFDictionarySetValue (mutableDict, kNetFSPathKey, tempString);
CFRelease(tempString);
CFRelease(Share);
Share = NULL;
}
}
}
if (Share && CFStringGetLength(Share))
CFDictionarySetValue (mutableDict, kNetFSPathKey, Share);
if (Share)
CFRelease(Share);
if (Path)
CFRelease(Path);
*dict = mutableDict;
return 0;
ErrorOut:
*dict = NULL;
if (mutableDict)
CFRelease(mutableDict);
if (!error)
error = EINVAL;
return error;
}
static int smb_dictionary_to_urlstring(CFDictionaryRef dict, CFMutableStringRef *urlReturnString)
{
int error = 0;
CFMutableStringRef urlStringM = NULL;
CFStringRef DomainWrkgrp = NULL;
CFStringRef Username = NULL;
CFStringRef Password = NULL;
CFStringRef Server = NULL;
CFStringRef PortNumber = NULL;
CFStringRef Path = NULL;
Boolean releaseUsername = FALSE;
char *ipV6Name = NULL;
urlStringM = CFStringCreateMutableCopy(NULL, 1024, CFSTR("smb://"));
if (urlStringM == NULL) {
error = errno;
smb_log_info("%s: couldn't allocate the url string, syserr = %s",
ASL_LEVEL_ERR, __FUNCTION__, strerror(error));
goto WeAreDone;
}
Server = CFDictionaryGetValue(dict, kNetFSHostKey);
ipV6Name = CStringCreateWithCFString(Server);
if (ipV6Name && isIPv6NumericName(ipV6Name)) {
CFMutableStringRef newServer = CFStringCreateMutableCopy(NULL, 1024, CFSTR("["));
if (newServer) {
CFStringAppend(newServer, Server);
CFStringAppend(newServer, CFSTR("]"));
Server = newServer;
CreateStringByAddingPercentEscapesUTF8(&Server, CFSTR("[]"), NULL, TRUE);
} else
Server = NULL;
} else {
CreateStringByAddingPercentEscapesUTF8(&Server, NULL, CFSTR("~!'()/@:,?=;&+$"), FALSE);
}
if (ipV6Name)
free(ipV6Name);
if (Server == NULL) {
error = EINVAL;
smb_log_info("%s: no server name, syserr = %s", ASL_LEVEL_ERR,
__FUNCTION__, strerror(error));
goto WeAreDone;
}
Username = CFDictionaryGetValue(dict, kNetFSUserNameKey);
if (Username) {
CFArrayRef userArray = NULL;
userArray = CreateWrkgrpUserArrayFromCFStringRef(Username, CFSTR("\\"));
if (userArray) {
DomainWrkgrp = CFStringCreateCopy(NULL, (CFStringRef)CFArrayGetValueAtIndex(userArray, 0));
Username = CFStringCreateCopy(NULL, (CFStringRef)CFArrayGetValueAtIndex(userArray, 1));
CFRelease(userArray);
releaseUsername = TRUE;
}
}
Password = CFDictionaryGetValue(dict, kNetFSPasswordKey);
Path = CFDictionaryGetValue(dict, kNetFSPathKey);
PortNumber = CFDictionaryGetValue(dict, kNetFSAlternatePortKey);
CreateStringByAddingPercentEscapesUTF8(&DomainWrkgrp, NULL, CFSTR("@:;/?"), TRUE);
CreateStringByAddingPercentEscapesUTF8(&Username, NULL, CFSTR("@:;/?"), releaseUsername);
CreateStringByAddingPercentEscapesUTF8(&Password, NULL, CFSTR("@:;/?"), FALSE);
CreateStringByAddingPercentEscapesUTF8(&Path, CFSTR("%%"), CFSTR("?#"), FALSE);
CreateStringByAddingPercentEscapesUTF8(&PortNumber, NULL, NULL, FALSE);
LogCFString(Username, "Username String", __FUNCTION__, __LINE__);
LogCFString(DomainWrkgrp, "Domain String", __FUNCTION__, __LINE__);
LogCFString(Path, "Path String", __FUNCTION__, __LINE__);
LogCFString(PortNumber, "PortNumber String", __FUNCTION__, __LINE__);
if (DomainWrkgrp) {
CFStringAppend(urlStringM, DomainWrkgrp);
CFStringAppend(urlStringM, CFSTR(";"));
}
if (Username || Password) {
if (Username)
CFStringAppend(urlStringM, Username);
if (Password) {
CFStringAppend(urlStringM, CFSTR(":"));
CFStringAppend(urlStringM, Password);
}
CFStringAppend(urlStringM, CFSTR("@"));
}
CFStringAppend(urlStringM, Server);
if (PortNumber) {
CFStringAppend(urlStringM, CFSTR(":"));
CFStringAppend(urlStringM, PortNumber);
}
if (Path) {
CFStringAppend(urlStringM, CFSTR("/"));
if ( kCFCompareEqualTo == CFStringCompare (Path, CFSTR("/"), kCFCompareCaseInsensitive) )
CFStringAppend(urlStringM, CFSTR("0x2f"));
else
CFStringAppend(urlStringM, Path);
}
DebugLogCFString(urlStringM, "URL String", __FUNCTION__, __LINE__);
WeAreDone:
if (Username)
CFRelease(Username);
if (Password)
CFRelease(Password);
if (DomainWrkgrp)
CFRelease(DomainWrkgrp);
if (Path)
CFRelease(Path);
if (PortNumber)
CFRelease(PortNumber);
if (Server)
CFRelease(Server);
if (error == 0)
*urlReturnString = urlStringM;
else if (urlStringM)
CFRelease(urlStringM);
return error;
}
int smb_dictionary_to_url(CFDictionaryRef dict, CFURLRef *url)
{
int error;
CFMutableStringRef urlStringM = NULL;
error = smb_dictionary_to_urlstring(dict, &urlStringM);
if ((error == 0) && urlStringM) {
*url = CFURLCreateWithString(NULL, urlStringM, NULL);
if (*url == NULL)
error = errno;
}
if (urlStringM)
CFRelease(urlStringM);
if (error)
smb_log_info("%s: creating the url failed, syserr = %s", ASL_LEVEL_ERR,
__FUNCTION__, strerror(error));
return error;
}
CFStringRef CreateURLCFString(CFStringRef Domain, CFStringRef Username, CFStringRef Password,
CFStringRef ServerName, CFStringRef Path, CFStringRef PortNumber)
{
CFMutableDictionaryRef mutableDict = NULL;
int error;
CFMutableStringRef urlString;
mutableDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (mutableDict == NULL) {
smb_log_info("%s: CFDictionaryCreateMutable failed, syserr = %s",
ASL_LEVEL_ERR, __FUNCTION__, strerror(errno));
return NULL;
}
if (Domain && Username) {
CFMutableStringRef tempString = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, Domain);
if (tempString) {
CFStringAppend(tempString, CFSTR("\\"));
CFStringAppend(tempString, Username);
Username = tempString;
} else {
CFRetain(Username);
}
} else if (Username) {
CFRetain(Username);
}
if (Username) {
CFDictionarySetValue(mutableDict, kNetFSUserNameKey, Username);
CFRelease(Username);
}
if (Password) {
CFDictionarySetValue(mutableDict, kNetFSPasswordKey, Password);
}
if (ServerName) {
CFDictionarySetValue(mutableDict, kNetFSHostKey, ServerName);
}
if (Path) {
CFDictionarySetValue (mutableDict, kNetFSPathKey, Path);
}
if (PortNumber) {
CFDictionarySetValue (mutableDict, kNetFSAlternatePortKey, PortNumber);
}
error = smb_dictionary_to_urlstring(mutableDict, &urlString);
CFRelease(mutableDict);
if (error) {
errno = error;
}
return urlString;
}
static void UpdateDictionaryWithUserAndShare(struct smb_ctx *ctx, CFMutableDictionaryRef mutableDict)
{
CFStringRef DomainWrkgrp = NULL;
CFStringRef Username = NULL;
CFStringRef share = NULL;
CFMutableStringRef path = NULL;
Username = CFDictionaryGetValue(mutableDict, kNetFSUserNameKey);
share = CFDictionaryGetValue(mutableDict, kNetFSPathKey);
if (share && Username)
return;
if (ctx->ct_setup.ioc_user[0]) {
Username = CFStringCreateWithCString(NULL, ctx->ct_setup.ioc_user, kCFStringEncodingUTF8);
if (ctx->ct_setup.ioc_domain[0])
DomainWrkgrp = CFStringCreateWithCString(NULL, ctx->ct_setup.ioc_domain, kCFStringEncodingUTF8);
if (DomainWrkgrp && Username && CFStringGetLength(Username)) {
CFMutableStringRef tempString = CFStringCreateMutableCopy(NULL, 0, DomainWrkgrp);
if (tempString) {
CFStringAppend(tempString, CFSTR("\\"));
CFStringAppend(tempString, Username);
CFRelease(Username);
Username = tempString;
}
}
if (DomainWrkgrp) {
CFRelease(DomainWrkgrp);
}
if (Username)
{
CFDictionarySetValue (mutableDict, kNetFSUserNameKey, Username);
CFRelease(Username);
}
}
if (share || !ctx->ct_origshare)
return;
path = CFStringCreateMutable(NULL, 1024);
if (!path)
return;
CFStringAppendCString(path, ctx->ct_origshare, kCFStringEncodingUTF8);
if (ctx->mountPath) {
CFStringAppend(path, CFSTR("/"));
CFStringAppend(path, ctx->mountPath);
}
CFDictionarySetValue (mutableDict, kNetFSPathKey, path);
CFRelease(path);
}
void CreateSMBFromName(struct smb_ctx *ctx, char *fromname, int maxlen)
{
CFMutableStringRef urlStringM = NULL;
CFMutableStringRef newUrlStringM = NULL;
CFMutableDictionaryRef mutableDict = NULL;
CFStringRef Password = NULL;
int SchemeLength = 0;
int error = 0;;
bzero(fromname, maxlen);
SchemeLength = SMBSchemeLength(ctx->ct_url);
urlStringM = CFStringCreateMutableCopy(NULL, 0, CFURLGetString(ctx->ct_url));
if (urlStringM == NULL) {
smb_log_info("Failed creating URL string, syserr = %s", ASL_LEVEL_ERR, strerror(errno));
return;
}
error = smb_url_to_dictionary(ctx->ct_url, (CFDictionaryRef *)&mutableDict);
if (error || (mutableDict == NULL)) {
smb_log_info("Failed parsing URL, syserr = %s", ASL_LEVEL_DEBUG, strerror(error));
goto WeAreDone;
}
UpdateDictionaryWithUserAndShare(ctx, mutableDict);
Password = CFDictionaryGetValue(mutableDict, kNetFSPasswordKey);
if (Password && (CFStringGetLength(Password) > 0)) {
CFDictionaryRemoveValue(mutableDict, kNetFSPasswordKey);
}
if (ctx->ct_setup.ioc_userflags & SMBV_GUEST_ACCESS)
CFDictionarySetValue (mutableDict, kNetFSPasswordKey, CFSTR(""));
error = smb_dictionary_to_urlstring(mutableDict, &newUrlStringM);
if (error || (newUrlStringM == NULL)) {
smb_log_info("Failed parsing dictionary, syserr = %s", ASL_LEVEL_DEBUG,
strerror(error));
goto WeAreDone;
}
if (urlStringM)
CFRelease(urlStringM);
urlStringM = newUrlStringM;
newUrlStringM = NULL;
SchemeLength = SMB_SCHEME_LEN;
if (CFStringGetLength(urlStringM) < (maxlen+SchemeLength))
goto WeAreDone;
CFDictionaryRemoveValue(mutableDict, kNetFSUserNameKey);
CFDictionaryRemoveValue(mutableDict, kNetFSPasswordKey);
error = smb_dictionary_to_urlstring(mutableDict, &newUrlStringM);
if (error || (newUrlStringM == NULL)) {
smb_log_info("Removing username failed parsing dictionary, syserr = %s",
ASL_LEVEL_DEBUG, strerror(error));
goto WeAreDone;
}
if (urlStringM)
CFRelease(urlStringM);
urlStringM = newUrlStringM;
newUrlStringM = NULL;
WeAreDone:
if (urlStringM && (SchemeLength > 0)) {
CFRange range1 = CFRangeMake(0, SchemeLength);
CFStringDelete(urlStringM, range1);
}
if (urlStringM)
CFStringGetCString(urlStringM, fromname, maxlen, kCFStringEncodingUTF8);
if (error)
smb_log_info("Mount from name is %s, syserr = %s", ASL_LEVEL_ERR,
fromname, strerror(error));
else
smb_log_info("Mount from name is %s", ASL_LEVEL_DEBUG, fromname);
if (urlStringM)
CFRelease(urlStringM);
if (mutableDict)
CFRelease(mutableDict);
}
int isBTMMAddress(CFStringRef serverNameRef)
{
boolean_t foundBTMM;
CFStringRef btmmRef;
CFStringRef serverNameQual;
CFIndex serverNameLen, btmmCount, serverCount, btmmIndex, srvIndex;
CFArrayRef btmmArrRef, serverArrRef;
CFStringRef btmmTmpRef, serverTmpRef;
CFComparisonResult res;
foundBTMM = TRUE;
btmmRef = NULL;
serverNameQual = NULL;
btmmArrRef = NULL;
serverArrRef = NULL;
if (serverNameRef == NULL) {
smb_log_info("%s: serverNameRef is NULL!", ASL_LEVEL_DEBUG, __FUNCTION__);
foundBTMM = FALSE;
goto out;
}
serverNameLen = CFStringGetLength(serverNameRef);
if (serverNameLen == 0) {
smb_log_info("%s: serverNameRef len is 0!", ASL_LEVEL_DEBUG, __FUNCTION__);
foundBTMM = FALSE;
goto out;
}
if (CFStringGetCharacterAtIndex(serverNameRef, serverNameLen - 1) == (UniChar)'.') {
serverNameQual = CFStringCreateCopy(kCFAllocatorDefault, serverNameRef);
} else {
serverNameQual = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@."), serverNameRef);
}
if (serverNameQual == NULL) {
foundBTMM = FALSE;
goto out;
}
btmmRef = _CSBackToMyMacCopyDomain();
if (btmmRef == NULL) {
foundBTMM = FALSE;
goto out;
}
btmmArrRef = CFStringCreateArrayBySeparatingStrings(kCFAllocatorDefault, btmmRef, CFSTR("."));
btmmCount = CFArrayGetCount(btmmArrRef);
serverArrRef = CFStringCreateArrayBySeparatingStrings(kCFAllocatorDefault, serverNameQual, CFSTR("."));
serverCount = CFArrayGetCount(serverArrRef);
if (btmmCount == 0 || serverCount == 0) {
foundBTMM = FALSE;
goto out;
}
if (btmmCount > serverCount) {
foundBTMM = FALSE;
goto out;
}
for (btmmIndex = btmmCount - 1, srvIndex = serverCount - 1; btmmIndex >= 0; btmmIndex--, srvIndex--) {
btmmTmpRef = CFArrayGetValueAtIndex(btmmArrRef, btmmIndex);
serverTmpRef = CFArrayGetValueAtIndex(serverArrRef, srvIndex);
res = CFStringCompare(btmmTmpRef, serverTmpRef, kCFCompareCaseInsensitive);
if (res != kCFCompareEqualTo) {
foundBTMM = FALSE;
break;
}
}
if (foundBTMM == TRUE) {
smb_log_info("%s: found a btmm address", ASL_LEVEL_DEBUG, __FUNCTION__);
}
out:
if (btmmArrRef != NULL) {
CFRelease(btmmArrRef);
}
if (serverArrRef != NULL) {
CFRelease(serverArrRef);
}
if (btmmRef != NULL) {
CFRelease(btmmRef);
}
if (serverNameQual !=NULL) {
CFRelease(serverNameQual);
}
return (foundBTMM);
}