1/* 2 * Copyright (c) 2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#include <sys/param.h> 25#include <sys/errno.h> 26#include <sys/stat.h> 27#include <err.h> 28#include <stdio.h> 29#include <unistd.h> 30#include <strings.h> 31#include <stdlib.h> 32#include <sysexits.h> 33#include <pwd.h> 34#include <membership.h> 35 36#include <smbclient/smbclient.h> 37#include <smbclient/smbclient_internal.h> 38#include <smbclient/ntstatus.h> 39 40#include "common.h" 41#include <netsmb/smb.h> 42 43static uint16_t 44uint16FromDictionary(CFDictionaryRef dict, CFStringRef key) 45{ 46 CFNumberRef num = CFDictionaryGetValue( dict, key); 47 uint16_t value = 0; 48 49 if( num ) { 50 CFNumberGetValue(num, kCFNumberSInt16Type, &value); 51 } 52 return value; 53} 54 55static void 56fprintfCFString(CFStringRef theString, const char *preStr, Boolean newLn) 57{ 58 char prntstr[1024]; 59 60 if (theString == NULL) { 61 fprintf(stdout, "%s(NULL)", preStr); 62 } else { 63 CFStringGetCString(theString, prntstr, 1024, kCFStringEncodingUTF8); 64 fprintf(stdout, "%s%s", preStr, prntstr); 65 } 66 if (newLn) { 67 fprintf(stdout, "\n"); 68 } 69} 70 71static void 72displayReferralList(CFArrayRef referralList) 73{ 74 CFIndex ii, count = (referralList) ? CFArrayGetCount(referralList) : 0; 75 76 if (!referralList) { 77 return; 78 } 79 for (ii = 0; ii < count; ii++) { 80 CFDictionaryRef dict = CFArrayGetValueAtIndex(referralList, ii); 81 82 fprintf(stdout, " list item %-2zu: ", ii+1); 83 fprintfCFString(CFDictionaryGetValue(dict, kDFSPath), "Path: ", TRUE); 84 fprintf(stdout, " list item %-2zu: ", ii+1); 85 fprintfCFString(CFDictionaryGetValue(dict, kNetworkAddress), 86 "Network Address: ", TRUE); 87 fprintf(stdout, " list item %-2zu: ", ii+1); 88 fprintfCFString(CFDictionaryGetValue(dict, kNewReferral), 89 "New Referral: ", TRUE); 90 } 91} 92 93static void 94displayDomainReferralList(CFArrayRef referralList) 95{ 96 CFArrayRef expandedNameArray; 97 CFIndex ii, count = (referralList) ? CFArrayGetCount(referralList) : 0; 98 99 if (!referralList) { 100 return; 101 } 102 for (ii = 0; ii < count; ii++) { 103 CFDictionaryRef dict = CFArrayGetValueAtIndex(referralList, ii); 104 CFIndex jj, exandedNameCount; 105 106 expandedNameArray = CFDictionaryGetValue(dict, kExpandedNameArray); 107 exandedNameCount = (expandedNameArray) ? CFArrayGetCount(expandedNameArray) : 0; 108 for (jj = 0; jj < exandedNameCount; jj++) { 109 fprintf(stdout, " "); 110 fprintfCFString(CFArrayGetValueAtIndex(expandedNameArray, jj), "ExpandedName: ", TRUE); 111 } 112 fprintf(stdout, " "); 113 fprintfCFString(CFDictionaryGetValue(dict, kSpecialName), "SpecialName: ", TRUE); 114 fprintf(stdout, " NumberOfExpandedNames: %d\n", uint16FromDictionary(dict, kNumberOfExpandedNames)); 115 fprintf(stdout, " ServerType: %d\n", uint16FromDictionary(dict, kServerType)); 116 } 117} 118 119int 120cmd_dfs(int argc, char *argv[]) 121{ 122 CFMutableDictionaryRef dfsReferralDict; 123 CFArrayRef dfsServerDictArray; 124 CFArrayRef dfsReferralDictArray; 125 CFIndex ad_count, count, ii; 126 const char *url = NULL; 127 int opt; 128 129 while ((opt = getopt(argc, argv, "h")) != EOF) { 130 switch(opt){ 131 case 'h': 132 default: 133 dfs_usage(); 134 /*NOTREACHED*/ 135 } 136 } 137 138 if (optind >= argc) { 139 dfs_usage(); 140 } 141 142 url = argv[optind]; 143 argc -= optind; 144 /* One more check to make sure we have the correct number of arguments */ 145 if (argc != 1) { 146 dfs_usage(); 147 } 148 149 dfsReferralDict = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, 150 &kCFTypeDictionaryKeyCallBacks, 151 &kCFTypeDictionaryValueCallBacks); 152 if (!dfsReferralDict) { 153 errno = ENOMEM; 154 err(EX_UNAVAILABLE, "internal error"); 155 } 156 157 SMBGetDfsReferral(url, dfsReferralDict); 158 159 /* Did we get a list of Domain Controllers from AD? */ 160 dfsServerDictArray = CFDictionaryGetValue(dfsReferralDict, 161 kDfsADServerArray); 162 163 ad_count = (dfsServerDictArray) ? CFArrayGetCount(dfsServerDictArray) : 0; 164 165 if (ad_count) { 166 fprintf(stdout, "\n"); 167 fprintf(stdout, "------------- AD Domain Entries -------------\n"); 168 169 for (ii = ad_count - 1; ii >= 0; ii--) { 170 CFStringRef dc = CFArrayGetValueAtIndex(dfsServerDictArray, ii); 171 172 if (dc) { 173 fprintfCFString(dc, "Server Name : ", TRUE); 174 } 175 } 176 } 177 178 /* 179 * Did we get a list of Domain Controllers from the server name that really 180 * was a domain name (ie GET_DFS_REFERRAL) 181 */ 182 dfsServerDictArray = CFDictionaryGetValue(dfsReferralDict, kDfsServerArray); 183 184 count = (dfsServerDictArray) ? CFArrayGetCount(dfsServerDictArray) : 0; 185 if (count) { 186 for (ii = count - 1; ii >= 0; ii--) { 187 CFDictionaryRef dict = CFArrayGetValueAtIndex(dfsServerDictArray, ii); 188 189 fprintf(stdout, "\n"); 190 fprintf(stdout, "------------- Domain Entry %-2zu -------------\n", count - ii); 191 if (dict) { 192 fprintfCFString(CFDictionaryGetValue(dict, kRequestFileName), 193 "Domain requested : ", TRUE); 194 displayDomainReferralList(CFDictionaryGetValue(dict, kReferralList)); 195 } 196 } 197 } 198 199 if (!ad_count && !count) { 200 fprintf(stdout, "\nNo server entries found\n"); 201 } 202 203 dfsReferralDictArray = CFDictionaryGetValue(dfsReferralDict, kDfsReferralArray); 204 count = (dfsReferralDictArray) ? CFArrayGetCount(dfsReferralDictArray) : 0; 205 if (!count) { 206 fprintf(stdout, "\nNo referral entries found\n"); 207 goto done; 208 } 209 for (ii = count-1; ii >= 0; ii--) { 210 CFDictionaryRef dict = CFArrayGetValueAtIndex(dfsReferralDictArray, ii); 211 212 fprintf(stdout, "\n"); 213 fprintf(stdout, "------------- Entry %-2zu -------------\n", count - ii); 214 if (dict) { 215 fprintfCFString(CFDictionaryGetValue(dict, kRequestFileName), 216 "Referral requested : ", TRUE); 217 displayReferralList(CFDictionaryGetValue(dict, kReferralList)); 218 } 219 } 220 221done: 222 fprintf(stdout, "\n"); 223 if (verbose) { 224 CFShow(dfsReferralDict); 225 } 226 CFRelease(dfsReferralDict); 227 return 0; 228} 229 230 231void 232dfs_usage(void) 233{ 234 fprintf(stderr, "usage: smbutil dfs smb://" 235 "[domain;][user[:password]@]" 236 "server/dfsroot/dfslink\n"); 237 exit(1); 238} 239