#include <sys/param.h>
#include <sys/errno.h>
#include <sys/stat.h>
#include <err.h>
#include <stdio.h>
#include <unistd.h>
#include <strings.h>
#include <stdlib.h>
#include <sysexits.h>
#include <pwd.h>
#include <membership.h>
#include <smbclient/smbclient.h>
#include <smbclient/smbclient_internal.h>
#include <smbclient/ntstatus.h>
#include "common.h"
#include <netsmb/smb.h>
static uint16_t
uint16FromDictionary(CFDictionaryRef dict, CFStringRef key)
{
CFNumberRef num = CFDictionaryGetValue( dict, key);
uint16_t value = 0;
if( num ) {
CFNumberGetValue(num, kCFNumberSInt16Type, &value);
}
return value;
}
static void
fprintfCFString(CFStringRef theString, const char *preStr, Boolean newLn)
{
char prntstr[1024];
if (theString == NULL) {
fprintf(stdout, "%s(NULL)", preStr);
} else {
CFStringGetCString(theString, prntstr, 1024, kCFStringEncodingUTF8);
fprintf(stdout, "%s%s", preStr, prntstr);
}
if (newLn) {
fprintf(stdout, "\n");
}
}
static void
displayReferralList(CFArrayRef referralList)
{
CFIndex ii, count = (referralList) ? CFArrayGetCount(referralList) : 0;
if (!referralList) {
return;
}
for (ii = 0; ii < count; ii++) {
CFDictionaryRef dict = CFArrayGetValueAtIndex(referralList, ii);
fprintf(stdout, " list item %-2zu: ", ii+1);
fprintfCFString(CFDictionaryGetValue(dict, kDFSPath), "Path: ", TRUE);
fprintf(stdout, " list item %-2zu: ", ii+1);
fprintfCFString(CFDictionaryGetValue(dict, kNetworkAddress),
"Network Address: ", TRUE);
fprintf(stdout, " list item %-2zu: ", ii+1);
fprintfCFString(CFDictionaryGetValue(dict, kNewReferral),
"New Referral: ", TRUE);
}
}
static void
displayDomainReferralList(CFArrayRef referralList)
{
CFArrayRef expandedNameArray;
CFIndex ii, count = (referralList) ? CFArrayGetCount(referralList) : 0;
if (!referralList) {
return;
}
for (ii = 0; ii < count; ii++) {
CFDictionaryRef dict = CFArrayGetValueAtIndex(referralList, ii);
CFIndex jj, exandedNameCount;
expandedNameArray = CFDictionaryGetValue(dict, kExpandedNameArray);
exandedNameCount = (expandedNameArray) ? CFArrayGetCount(expandedNameArray) : 0;
for (jj = 0; jj < exandedNameCount; jj++) {
fprintf(stdout, " ");
fprintfCFString(CFArrayGetValueAtIndex(expandedNameArray, jj), "ExpandedName: ", TRUE);
}
fprintf(stdout, " ");
fprintfCFString(CFDictionaryGetValue(dict, kSpecialName), "SpecialName: ", TRUE);
fprintf(stdout, " NumberOfExpandedNames: %d\n", uint16FromDictionary(dict, kNumberOfExpandedNames));
fprintf(stdout, " ServerType: %d\n", uint16FromDictionary(dict, kServerType));
}
}
int
cmd_dfs(int argc, char *argv[])
{
CFMutableDictionaryRef dfsReferralDict;
CFArrayRef dfsServerDictArray;
CFArrayRef dfsReferralDictArray;
CFIndex count, ii;
const char *url = NULL;
int opt;
while ((opt = getopt(argc, argv, "h")) != EOF) {
switch(opt){
case 'h':
default:
dfs_usage();
}
}
if (optind >= argc)
dfs_usage();
url = argv[optind];
argc -= optind;
if (argc != 1)
dfs_usage();
dfsReferralDict = CFDictionaryCreateMutable( kCFAllocatorSystemDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (!dfsReferralDict) {
errno = ENOMEM;
err(EX_UNAVAILABLE, "internal error");
}
SMBGetDfsReferral(url, dfsReferralDict);
dfsServerDictArray = CFDictionaryGetValue(dfsReferralDict, kDfsServerArray);
count = (dfsServerDictArray) ? CFArrayGetCount(dfsServerDictArray) : 0;
if (!count) {
fprintf(stdout, "\nNo server entries found\n");
}
for (ii = count-1; ii >= 0; ii--) {
CFDictionaryRef dict = CFArrayGetValueAtIndex(dfsServerDictArray, ii);
fprintf(stdout, "\n");
fprintf(stdout, "------------- Domain Entry %-2zu -------------\n", count - ii);
if (dict) {
fprintfCFString(CFDictionaryGetValue(dict, kRequestFileName),
"Domain requested : ", TRUE);
displayDomainReferralList(CFDictionaryGetValue(dict, kReferralList));
}
}
dfsReferralDictArray = CFDictionaryGetValue(dfsReferralDict, kDfsReferralArray);
count = (dfsReferralDictArray) ? CFArrayGetCount(dfsReferralDictArray) : 0;
if (!count) {
fprintf(stdout, "\nNo referral entries found\n");
goto done;
}
for (ii = count-1; ii >= 0; ii--) {
CFDictionaryRef dict = CFArrayGetValueAtIndex(dfsReferralDictArray, ii);
fprintf(stdout, "\n");
fprintf(stdout, "------------- Entry %-2zu -------------\n", count - ii);
if (dict) {
fprintfCFString(CFDictionaryGetValue(dict, kRequestFileName),
"Referral requested : ", TRUE);
displayReferralList(CFDictionaryGetValue(dict, kReferralList));
}
}
done:
fprintf(stdout, "\n");
if (verbose) {
CFShow(dfsReferralDict);
}
CFRelease(dfsReferralDict);
return 0;
}
void
dfs_usage(void)
{
fprintf(stderr, "usage: smbutil dfs smb://"
"[domain;][user[:password]@]"
"server/dfsroot/dfslink\n");
exit(1);
}