1/* 2 * Copyright (c) 2012 - 2013 Apple Inc. All rights reserved 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Apple Inc. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 */ 33 34#include <sys/param.h> 35#include <sys/ucred.h> 36#include <sys/mount.h> 37#include <sys/errno.h> 38#include <sys/stat.h> 39#include <err.h> 40#include <stdio.h> 41#include <unistd.h> 42#include <strings.h> 43#include <stdlib.h> 44#include <sysexits.h> 45 46#include <smbclient/smbclient.h> 47#include <smbclient/smbclient_internal.h> 48#include <smbclient/smbclient_private.h> 49#include <smbclient/smbclient_netfs.h> 50#include <smbclient/ntstatus.h> 51 52#include <netsmb/smb_lib.h> 53#include <netsmb/smb_dev.h> 54#include <netsmb/smbio.h> 55#include <netsmb/smbio_2.h> 56#include <netsmb/smb_2.h> 57#include <netsmb/smb_conn.h> 58 59#include "common.h" 60#include "netshareenum.h" 61 62static void 63print_header(FILE *fp) 64{ 65 fprintf(fp, "\n================================================"); 66 fprintf(fp, "==================================================\n"); 67 fprintf(fp, "%-30s%-30s%s\n", "SHARE", "ATTRIBUTE TYPE", "VALUE"); 68 fprintf(fp, "=================================================="); 69 fprintf(fp, "================================================\n"); 70} 71 72static void 73print_if_attr(FILE *fp, uint64_t flag, uint64_t of_type, 74 const char *attr, const char *attr_val, int *isattr) 75{ 76 if (*isattr == -1) 77 fprintf(fp, "%-30s%-30s%s\n", "", attr, attr_val); 78 else if (flag & of_type) { 79 fprintf(fp, "%-30s%-30s%s\n", "", attr, attr_val); 80 *isattr = 1; 81 } 82} 83 84static void 85print_if_attr_chk_ret(FILE *fp, uint64_t flag, uint64_t of_type, 86 const char *attr, const char *attr_val, int *ret) 87{ 88 if (!(*ret)) { 89 *ret = -1; 90 print_if_attr(fp, flag, of_type, attr, attr_val, ret); 91 } 92 *ret = 0; 93} 94 95static void 96print_delimeter(FILE *fp) 97{ 98 fprintf(fp, "\n------------------------------------------------"); 99 fprintf(fp, "--------------------------------------------------\n"); \ 100} 101 102static void 103interpret_and_display(char *share, SMBShareAttributes *sattrs) 104{ 105 int ret = 0; 106 107 /* share name and server */ 108 fprintf(stdout, "%-30s\n", share); 109 fprintf(stdout, "%-30s%-30s%s\n", "", "SERVER_NAME", sattrs->server_name); 110 111 /* user who mounted this share */ 112 fprintf(stdout, "%-30s%-30s%d\n", "","USER_ID", sattrs->vc_uid); 113 114 /* smb negotiate */ 115 print_if_attr(stdout, sattrs->vc_misc_flags, 116 SMBV_NEG_SMB1_ONLY, "SMB_NEGOTIATE", 117 "SMBV_NEG_SMB1_ONLY", &ret); 118 print_if_attr(stdout, sattrs->vc_misc_flags, 119 SMBV_NEG_SMB2_ONLY, "SMB_NEGOTIATE", 120 "SMBV_NEG_SMB2_ONLY", &ret); 121 print_if_attr(stdout, sattrs->vc_misc_flags, 122 SMBV_NEG_SMB3_ONLY, "SMB_NEGOTIATE", 123 "SMBV_NEG_SMB3_ONLY", &ret); 124 print_if_attr_chk_ret(stdout, 0, 125 0, "SMB_NEGOTIATE", 126 "AUTO_NEGOTIATE", &ret); 127 128 /* smb version */ 129 print_if_attr(stdout, sattrs->vc_flags, 130 SMBV_SMB302, "SMB_VERSION", 131 "SMB_3.02", &ret); 132 print_if_attr(stdout, sattrs->vc_flags, 133 SMBV_SMB30, "SMB_VERSION", 134 "SMB_3.0", &ret); 135 print_if_attr(stdout, sattrs->vc_flags, 136 SMBV_SMB2002, "SMB_VERSION", 137 "SMB_2.002", &ret); 138 print_if_attr(stdout, sattrs->vc_flags, 139 SMBV_SMB21, "SMB_VERSION", 140 "SMB_2.1", &ret); 141 print_if_attr_chk_ret(stdout, 0, 142 0, "SMB_VERSION", 143 "SMB_1", &ret); 144 145 /* 146 * Note: No way to get file system type since the type is determined at 147 * mount time and not just by a Tree Connect. If we ever wanted to display 148 * the file system type, we would probably need an IOCTL to the mount 149 * point to get the information. 150 */ 151 152 /* Share type */ 153 switch (sattrs->ss_type) { 154 case SMB2_SHARE_TYPE_DISK: 155 print_if_attr(stdout, 1, 1, "SMB_SHARE_TYPE", "DISK", &ret); 156 break; 157 158 case SMB2_SHARE_TYPE_PIPE: 159 print_if_attr(stdout, 1, 1, "SMB_SHARE_TYPE", "PIPE", &ret); 160 break; 161 162 case SMB2_SHARE_TYPE_PRINT: 163 print_if_attr(stdout, 1, 1, "SMB_SHARE_TYPE", "PRINT", &ret); 164 break; 165 166 default: 167 print_if_attr_chk_ret(stdout, 0, 0, "SMB_SHARE_TYPE", "UNKNOWN", 168 &ret); 169 break; 170 } 171 172 /* smb server capabilities */ 173 print_if_attr(stdout, sattrs->vc_flags, 174 SMBV_SIGNING, "SIGNING_SUPPORTED", 175 "TRUE", &ret); 176 print_if_attr(stdout, sattrs->vc_flags, 177 SMBV_SIGNING_REQUIRED, "SIGNING_REQUIRED", 178 "TRUE", &ret); 179 print_if_attr(stdout, sattrs->vc_smb1_caps, 180 SMB_CAP_EXT_SECURITY, "EXTENDED_SECURITY_SUPPORTED", 181 "TRUE", &ret); 182 print_if_attr(stdout, sattrs->vc_smb1_caps, 183 SMB_CAP_UNIX, "UNIX_SUPPORT", 184 "TRUE", &ret); 185 print_if_attr(stdout, sattrs->vc_smb1_caps, 186 SMB_CAP_LARGE_FILES, "LARGE_FILE_SUPPORTED", 187 "TRUE", &ret); 188 189 /* SMB 2/3 capabilities */ 190 print_if_attr(stdout, sattrs->vc_misc_flags, 191 SMBV_OSX_SERVER, "OS_X_SERVER", 192 "TRUE", &ret); 193 print_if_attr(stdout, sattrs->vc_misc_flags, 194 SMBV_CLIENT_SIGNING_REQUIRED, "CLIENT_REQUIRES_SIGNING", 195 "TRUE", &ret); 196 print_if_attr(stdout, sattrs->vc_misc_flags, 197 SMBV_HAS_FILEIDS, "FILE_IDS_SUPPORTED", 198 "TRUE", &ret); 199 print_if_attr(stdout, sattrs->vc_misc_flags, 200 SMBV_NO_QUERYINFO, "QUERYINFO_NOT_SUPPORTED", 201 "TRUE", &ret); 202 203 print_if_attr(stdout, sattrs->vc_smb2_caps, 204 SMB2_GLOBAL_CAP_DFS, "DFS_SUPPORTED", 205 "TRUE", &ret); 206 print_if_attr(stdout, sattrs->vc_smb2_caps, 207 SMB2_GLOBAL_CAP_LEASING, "FILE_LEASING_SUPPORTED", 208 "TRUE", &ret); 209 print_if_attr(stdout, sattrs->vc_smb2_caps, 210 SMB2_GLOBAL_CAP_LARGE_MTU, "MULTI_CREDIT_SUPPORTED", 211 "TRUE", &ret); 212 print_if_attr(stdout, sattrs->vc_smb2_caps, 213 SMB2_GLOBAL_CAP_MULTI_CHANNEL, "MULTI_CHANNEL_SUPPORTED", 214 "TRUE", &ret); 215 print_if_attr(stdout, sattrs->vc_smb2_caps, 216 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES, "PERSISTENT_HANDLES_SUPPORTED", 217 "TRUE", &ret); 218 print_if_attr(stdout, sattrs->vc_smb2_caps, 219 SMB2_GLOBAL_CAP_DIRECTORY_LEASING, "DIR_LEASING_SUPPORTED", 220 "TRUE", &ret); 221 print_if_attr(stdout, sattrs->vc_smb2_caps, 222 SMB2_GLOBAL_CAP_ENCRYPTION, "ENCRYPTION_SUPPORTED", 223 "TRUE", &ret); 224 225 print_if_attr_chk_ret(stdout, 0, 226 0, "SERVER_CAPS", 227 "UNKNOWN", &ret); 228 229 /* other share attributes */ 230 print_if_attr(stdout, sattrs->ss_attrs, 231 FILE_READ_ONLY_VOLUME, "VOLUME_RDONLY", 232 "TRUE", &ret); 233 print_if_attr(stdout, sattrs->ss_caps, 234 SMB2_SHARE_CAP_DFS, "DFS_SHARE", 235 "TRUE", &ret); 236 /* Sealing current status */ 237 print_if_attr(stdout, sattrs->ss_flags, 238 SMB2_SHAREFLAG_ENCRYPT_DATA, "ENCRYPTION_REQUIRED", 239 "TRUE", &ret); 240 241 /* Signing current status */ 242 print_if_attr(stdout, sattrs->vc_hflags2, 243 SMB_FLAGS2_SECURITY_SIGNATURE, "SIGNING_ON", 244 "TRUE", &ret); 245 246 if (verbose) { 247 fprintf(stdout, "vc_flags: 0x%x\n", sattrs->vc_flags); 248 fprintf(stdout, "vc_hflags: 0x%x\n", sattrs->vc_hflags); 249 fprintf(stdout, "vc_hflags2: 0x%x\n", sattrs->vc_hflags2); 250 fprintf(stdout, "vc_misc_flags: 0x%llx\n", sattrs->vc_misc_flags); 251 fprintf(stdout, "vc_smb1_caps: 0x%x\n", sattrs->vc_smb1_caps); 252 fprintf(stdout, "vc_smb2_caps: 0x%x\n", sattrs->vc_smb2_caps); 253 fprintf(stdout, "vc_uid: 0x%x\n", sattrs->vc_uid); 254 255 fprintf(stdout, "ss_attrs: 0x%x\n", sattrs->ss_attrs); 256 fprintf(stdout, "ss_caps: 0x%x\n", sattrs->ss_caps); 257 fprintf(stdout, "ss_flags: 0x%x\n", sattrs->ss_flags); 258 fprintf(stdout, "ss_fstype: 0x%x\n", sattrs->ss_fstype); 259 fprintf(stdout, "ss_type: 0x%x\n", sattrs->ss_type); 260 } 261} 262 263static NTSTATUS 264stat_share(char *share_mp, bool disablePrintingHeader) 265{ 266 SMBHANDLE inConnection = NULL; 267 NTSTATUS status = STATUS_SUCCESS; 268 struct statfs statbuf; 269 char tmp_name[MNAMELEN]; 270 char *share_name = NULL, *end = NULL; 271 272 if ((statfs((const char*)share_mp, &statbuf) == -1) || (strncmp(statbuf.f_fstypename, "smbfs", 5) != 0)) { 273 status = STATUS_INVALID_PARAMETER; 274 errno = EINVAL; 275 return status; 276 } 277 278 /* 279 * Need to specify a share name, else you get IPC$ 280 * Use the f_mntfromname so we dont have to worry about -1, -2 on the 281 * mountpath and skip the initial "//" 282 */ 283 strlcpy(tmp_name, &statbuf.f_mntfromname[2], sizeof(tmp_name)); 284 share_name = strchr(tmp_name, '/'); 285 if (share_name != NULL) { 286 /* skip over the / to point at share name */ 287 share_name += 1; 288 289 /* Check for submount and if found, strip it off */ 290 end = strchr(share_name, '/'); 291 if (end != NULL) { 292 /* Found submount, just null it out as we only want sharepoint */ 293 *end = 0x00; 294 } 295 } 296 else { 297 fprintf(stderr, "%s : Failed to find share name in %s\n", 298 __FUNCTION__, statbuf.f_mntfromname); 299 status = STATUS_INVALID_PARAMETER; 300 errno = EINVAL; 301 return status; 302 } 303 304 status = SMBOpenServerWithMountPoint(share_mp, 305 share_name, 306 &inConnection, 307 0); 308 if (!NT_SUCCESS(status)) { 309 fprintf(stderr, "%s : SMBOpenServerWithMountPoint() failed for %s <%s>\n", 310 __FUNCTION__, share_mp, share_name); 311 } 312 else { 313 SMBShareAttributes sattrs; 314 315 status = SMBGetShareAttributes(inConnection, &sattrs); 316 if (!NT_SUCCESS(status)) { 317 fprintf(stderr, "%s : SMBGetShareAttributes() failed for %s <%s>\n", 318 __FUNCTION__, share_mp, share_name); 319 } 320 else { 321 if (!disablePrintingHeader) 322 print_header(stdout); 323 324 interpret_and_display(share_name, &sattrs); 325 print_delimeter(stdout); 326 } 327 SMBReleaseServer(inConnection); 328 } 329 330 return status; 331} 332 333static NTSTATUS 334stat_all_shares() 335{ 336 NTSTATUS error = STATUS_SUCCESS; 337 struct statfs *fs = NULL; 338 int fs_cnt = 0; 339 int i = 0; 340 int disablePrintingHeader = 1; 341 342 fs = smb_getfsstat(&fs_cnt); 343 if (!fs || fs_cnt < 0) 344 return ENOENT; 345 print_header(stdout); 346 for (i = 0; i < fs_cnt; i++, fs++) { 347 NTSTATUS status; 348 349 if (strncmp(fs->f_fstypename, "smbfs", 5) != 0) 350 continue; 351 if (fs->f_flags & MNT_AUTOMOUNTED) 352 continue; 353 354 status = stat_share(fs->f_mntonname, disablePrintingHeader) ; 355 if (!NT_SUCCESS(status)) { 356 fprintf(stderr, "%s : stat_share() failed for %s\n", 357 __FUNCTION__, fs->f_mntonname); 358 print_delimeter(stderr); 359 error = status; 360 } 361 } 362 363 return error; 364} 365 366int 367cmd_statshares(int argc, char *argv[]) 368{ 369 NTSTATUS status = STATUS_SUCCESS; 370 int opt; 371 bool disablePrintingHeader = 0; 372 373 if ((opt = getopt(argc, argv, "am:")) != EOF) { 374 switch(opt) { 375 case 'a': 376 if (argc != 2) 377 statshares_usage(); 378 status = stat_all_shares(); 379 break; 380 case 'm': 381 if (argc != 3) 382 statshares_usage(); 383 status = stat_share(optarg, disablePrintingHeader); 384 break; 385 default: 386 break; 387 } 388 } 389 else 390 statshares_usage(); 391 392 if (!NT_SUCCESS(status)) 393 ntstatus_to_err(status); 394 395 return 0; 396} 397 398void 399statshares_usage(void) 400{ 401 fprintf(stderr, "usage : smbutil statshares [-m <mount_path>] | [-a]\n"); 402 fprintf(stderr, "\ 403 [\n \ 404 description :\n \ 405 -a : attributes of all mounted shares\n \ 406 -m <mount_path> : attributes of share mounted at mount_path\n \ 407 ]\n"); 408 exit(1); 409} 410