#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 <smbclient/smbclient.h>
#include <smbclient/ntstatus.h>
#include "common.h"
#include "netshareenum.h"
static char *CStringCreateWithCFString(CFStringRef inStr)
{
CFIndex maxLen;
char *str;
if (inStr == NULL) {
return NULL;
}
maxLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(inStr),
kCFStringEncodingUTF8) + 1;
str = malloc(maxLen);
if (!str) {
return NULL;
}
CFStringGetCString(inStr, str, maxLen, kCFStringEncodingUTF8);
return str;
}
static CFArrayRef createShareArrayFromShareDictionary(CFDictionaryRef shareDict)
{
CFIndex count = CFDictionaryGetCount(shareDict);
CFArrayRef keyArray = NULL;
void *shareKeys = CFAllocatorAllocate(kCFAllocatorDefault, count * sizeof(CFStringRef), 0);
if (shareKeys) {
CFDictionaryGetKeysAndValues(shareDict, shareKeys, NULL);
keyArray = CFArrayCreate(kCFAllocatorDefault, shareKeys, count, &kCFTypeArrayCallBacks);
CFAllocatorDeallocate(kCFAllocatorDefault, shareKeys);
}
return keyArray;
}
int
cmd_view(int argc, char *argv[])
{
const char *url = NULL;
int opt;
SMBHANDLE serverConnection = NULL;
uint64_t options = 0;
NTSTATUS status;
int error;
CFDictionaryRef shareDict= NULL;
while ((opt = getopt(argc, argv, "ANGgaf")) != EOF) {
switch(opt){
case 'A':
options |= kSMBOptionSessionOnly;
break;
case 'N':
options |= kSMBOptionNoPrompt;
break;
case 'G':
options |= kSMBOptionAllowGuestAuth;
break;
case 'g':
if (options & kSMBOptionOnlyAuthMask)
view_usage();
options |= kSMBOptionUseGuestOnlyAuth;
options |= kSMBOptionNoPrompt;
break;
case 'a':
if (options & kSMBOptionOnlyAuthMask)
view_usage();
options |= kSMBOptionUseAnonymousOnlyAuth;
options |= kSMBOptionNoPrompt;
break;
case 'f':
options |= kSMBOptionForceNewSession;
break;
default:
view_usage();
}
}
if (optind >= argc)
view_usage();
url = argv[optind];
argc -= optind;
if (argc != 1)
view_usage();
status = SMBOpenServerEx(url, &serverConnection, options);
if (!NT_SUCCESS(status)) {
ntstatus_to_err(status);
}
if (options & kSMBOptionSessionOnly) {
fprintf(stdout, "Authenticate successfully with %s\n", url);
goto done;
}
fprintf(stdout, "%-48s%-8s%s\n", "Share", "Type", "Comments");
fprintf(stdout, "-------------------------------\n");
error = smb_netshareenum(serverConnection, &shareDict, FALSE);
if (error) {
errno = error;
SMBReleaseServer(serverConnection);
err(EX_IOERR, "unable to list resources");
} else {
CFArrayRef shareArray = createShareArrayFromShareDictionary(shareDict);
CFStringRef shareStr, shareTypeStr, commentStr;
CFDictionaryRef theDict;
CFIndex ii;
char *share, *sharetype, *comments;
for (ii=0; shareArray && (ii < CFArrayGetCount(shareArray)); ii++) {
shareStr = CFArrayGetValueAtIndex(shareArray, ii);
if (shareStr == NULL) {
continue;
}
theDict = CFDictionaryGetValue(shareDict, shareStr);
if (theDict == NULL) {
continue;
}
shareTypeStr = CFDictionaryGetValue(theDict, kNetShareTypeStrKey);
commentStr = CFDictionaryGetValue(theDict, kNetCommentStrKey);
share = CStringCreateWithCFString(shareStr);
sharetype = CStringCreateWithCFString(shareTypeStr);
comments = CStringCreateWithCFString(commentStr);
fprintf(stdout, "%-48s%-8s%s\n", share ? share : "",
sharetype ? sharetype : "", comments ? comments : "");
free(share);
free(sharetype);
free(comments);
}
fprintf(stdout, "\n%ld shares listed\n", CFArrayGetCount(shareArray));
if (shareArray) {
CFRelease(shareArray);
}
if (shareDict) {
CFRelease(shareDict);
}
}
done:
SMBReleaseServer(serverConnection);
return 0;
}
void
view_usage(void)
{
fprintf(stderr, "usage: smbutil view [connection options] //"
"[domain;][user[:password]@]"
"server\n");
fprintf(stderr, "where options are:\n"
" -A authorize only\n"
" -N don't prompt for a password\n"
" -G allow guest access\n"
" -g authorize with guest only\n"
" -a authorize with anonymous only\n"
" -f don't share session\n");
exit(1);
}