/* * SMBNetFsCloseSession */ int32_t SMBNetFsCloseSession(SMBHANDLE inConnection) { NTSTATUS status = SMBReleaseServer(inConnection); if (NT_SUCCESS(status)) { return 0; } return errno; }
int SMBGetDfsReferral(const char * url, CFMutableDictionaryRef dfsReferralDict) { int error; NTSTATUS status; SMBHANDLE serverConnection; void * hContext = NULL; if (!dfsReferralDict) { errno = EINVAL; return -1; } status = SMBOpenServerEx(url, &serverConnection, kSMBOptionSessionOnly); /* SMBOpenServerEx sets errno, */ if (!NT_SUCCESS(status)) { return -1; } status = SMBServerContext(serverConnection, &hContext); if (!NT_SUCCESS(status)) { /* Couldn't get the context? */ SMBReleaseServer(serverConnection); return -1; } error = getDfsReferralList(hContext, dfsReferralDict); if (error) { SMBReleaseServer(serverConnection); errno = error; return -1; } SMBReleaseServer(serverConnection); return 0; }
int main(int argc, char *argv[]) { SMBHANDLE serverConnection = NULL; uint64_t options = kSMBOptionSessionOnly; uint64_t mntOptions = 0; int altflags = SMBFS_MNT_STREAMS_ON; mode_t fileMode = 0, dirMode = 0; int mntflags = 0; NTSTATUS status; char mountPoint[MAXPATHLEN]; struct stat st; char *next; int opt; const char * url = NULL; int version = SMBFrameworkVersion(); while ((opt = getopt(argc, argv, "Nvhd:f:o:")) != -1) { switch (opt) { case 'd': errno = 0; dirMode = strtol(optarg, &next, 8); if (errno || *next != 0) errx(EX_DATAERR, "invalid value for directory mode"); break; case 'f': errno = 0; fileMode = strtol(optarg, &next, 8); if (errno || *next != 0) errx(EX_DATAERR, "invalid value for file mode"); break; case 'N': options |= kSMBOptionNoPrompt; break; case 'o': { mntoptparse_t mp = getmntopts(optarg, mopts, &mntflags, &altflags); if (mp == NULL) err(1, NULL); freemntopts(mp); break; } case 'v': errx(EX_OK, "version %d.%d.%d", version / 100000, (version % 10000) / 1000, (version % 1000) / 100); break; case '?': case 'h': default: usage(); break; } } if (optind >= argc) usage(); argc -= optind; /* At this point we should only have a url and a mount point */ if (argc != 2) usage(); url = argv[optind]; optind++; realpath(unpercent(argv[optind]), mountPoint); if (stat(mountPoint, &st) == -1) err(EX_OSERR, "could not find mount point %s", mountPoint); if (!S_ISDIR(st.st_mode)) { errno = ENOTDIR; err(EX_OSERR, "can't mount on %s", mountPoint); } if (mntflags & MNT_AUTOMOUNTED) { /* Automount volume, don't look in the user home directory */ options |= kSMBOptionNoUserPreferences; } if ((altflags & SMBFS_MNT_STREAMS_ON) != SMBFS_MNT_STREAMS_ON) { /* They told us to turn of named streams */ mntOptions |= kSMBMntOptionNoStreams; } if ((altflags & SMBFS_MNT_NOTIFY_OFF) == SMBFS_MNT_NOTIFY_OFF) { /* They told us to turn off remote notifications */ mntOptions |= kSMBMntOptionNoNotifcations; } if ((altflags & SMBFS_MNT_SOFT) == SMBFS_MNT_SOFT) { /* Make this a soft mount */ mntOptions |= kSMBMntOptionSoftMount; } if ((altflags & SMBFS_MNT_TIME_MACHINE) == SMBFS_MNT_TIME_MACHINE) { /* Make this a tm mount */ mntOptions |= kSMBReservedTMMount; } status = SMBOpenServerEx(url, &serverConnection, options); if (NT_SUCCESS(status)) { status = SMBMountShareEx(serverConnection, NULL, mountPoint, mntflags, mntOptions, fileMode, dirMode, setNetworkAccountSID, NULL); } /* * SMBOpenServerEx now sets errno, so err will work correctly. We change * the string based on the NTSTATUS Error. */ if (!NT_SUCCESS(status)) { switch (status) { case STATUS_NO_SUCH_DEVICE: err(EX_UNAVAILABLE, "failed to intitialize the smb library"); break; case STATUS_LOGON_FAILURE: err(EX_NOPERM, "server rejected the connection"); break; case STATUS_CONNECTION_REFUSED: err(EX_NOHOST, "server connection failed"); break; case STATUS_INVALID_HANDLE: case STATUS_NO_MEMORY: err(EX_UNAVAILABLE, "internal error"); break; case STATUS_UNSUCCESSFUL: err(EX_USAGE, "mount error: %s", mountPoint); break; case STATUS_INVALID_PARAMETER: err(EX_USAGE, "URL parsing failed, please correct the URL and try again"); break; case STATUS_BAD_NETWORK_NAME: err(EX_NOHOST, "share connection failed"); break; default: err(EX_OSERR, "unknown status %d", status); break; } } /* We are done clean up anything left around */ if (serverConnection) SMBReleaseServer(serverConnection); return 0; }
NTSTATUS SMBOpenServerWithMountPoint( const char * pTargetMountPath, const char * pTargetTreeName, SMBHANDLE * outConnection, uint64_t options) { NTSTATUS status; int err; void * hContext; struct statfs statbuf; *outConnection = NULL; status = SMBLibraryInit(); if (!NT_SUCCESS(status)) { goto done; } /* Need to get the mount from name, use that as the URL */ err = statfs(pTargetMountPath, &statbuf); if (err) { status = STATUS_OBJECT_PATH_NOT_FOUND; goto done; } status = SMBAllocateServer(outConnection, statbuf.f_mntfromname); if (!NT_SUCCESS(status)) { goto done; } status = SMBServerContext(*outConnection, &hContext); if (!NT_SUCCESS(status)) { goto done; } /* Need to clear out the user name field */ smb_ctx_setuser(hContext, ""); err = findMountPointVC(hContext, pTargetMountPath); if (err) { status = STATUS_OBJECT_NAME_NOT_FOUND; errno = err; goto done; } if (options & kSMBOptionSessionOnly) { goto done; } /* No tree name, let's assume that the caller means IPC$ */ if (!pTargetTreeName) { pTargetTreeName = "IPC$"; } err = smb_ctx_setshare(hContext, pTargetTreeName); if (err) { if (err == ENAMETOOLONG) { status = STATUS_NAME_TOO_LONG; } else { status = STATUS_NO_MEMORY; } errno = err; goto done; } /* OK, now we have a virtual circuit but no tree connection yet. */ err = smb_share_connect((*outConnection)->context); if (err) { status = STATUS_BAD_NETWORK_NAME; errno = err; goto done; } status = STATUS_SUCCESS; done: if ((!NT_SUCCESS(status)) && *outConnection) { SMBReleaseServer(*outConnection); *outConnection = NULL; } return status; }
NTSTATUS SMBOpenServerEx( const char * targetServer, SMBHANDLE * outConnection, uint64_t options) { NTSTATUS status; int err; void * hContext; CFMutableDictionaryRef netfsOptions = NULL; CFDictionaryRef ServerParams = NULL; *outConnection = NULL; status = SMBLibraryInit(); if (!NT_SUCCESS(status)) { goto done; } netfsOptions = SMBCreateDefaultOptions(options); if (netfsOptions == NULL) { status = STATUS_NO_MEMORY; goto done; } status = SMBAllocateServer(outConnection, targetServer); if (!NT_SUCCESS(status)) { goto done; } status = SMBServerContext(*outConnection, &hContext); if (!NT_SUCCESS(status)) { goto done; } err = smb_get_server_info(hContext, NULL, netfsOptions, &ServerParams); if (err) { /* XXX map real NTSTATUS code */ status = STATUS_CONNECTION_REFUSED; errno = err; goto done; } /* * They didn't set the force new session option and we have a shared session, * then we are done. We have a connection and we are authenticated. */ if (!(options & kSMBOptionForceNewSession) && (((struct smb_ctx *)hContext)->ct_vc_shared)) { goto authDone; } /* * They have guest as the username in the url, then they want us to * force guest access. */ if (((struct smb_ctx *)hContext)->ct_setup.ioc_userflags & SMBV_GUEST_ACCESS) { options |= kSMBOptionUseGuestOnlyAuth; } /* Connect using Guest Access only */ if (options & kSMBOptionUseGuestOnlyAuth) { status = SMBServerConnect(*outConnection, NULL, netfsOptions, kSMBAuthTypeGuest); goto authDone; } /* Connect using Anonymous Access only */ if (options & kSMBOptionUseAnonymousOnlyAuth) { status = SMBServerConnect(*outConnection, NULL, netfsOptions, kSMBAuthTypeAnonymous); goto authDone; } /* Attempt an authenticated connect, could be kerberos or ntlm. */ status = SMBServerConnect(*outConnection, NULL, netfsOptions, kSMBAuthTypeAuthenticated); if (NT_SUCCESS(status)) { goto authDone; } /* See if we need to prompt for a password */ if (SMBPasswordPrompt(*outConnection, options)) { /* Attempt an authenticated connect again , could be kerberos or ntlm. */ status = SMBServerConnect(*outConnection, NULL, netfsOptions, kSMBAuthTypeAuthenticated); if (NT_SUCCESS(status)) { goto authDone; } } /* Kerberos and NTLM failed, attempt Guest access if option set */ if (options & kSMBOptionAllowGuestAuth) { status = SMBServerConnect(*outConnection, NULL, netfsOptions, kSMBAuthTypeGuest); if (NT_SUCCESS(status)) { goto authDone; } } /* Kerberos and NTLM failed, attempt Anonymous access if option set */ if (options & kSMBOptionAllowAnonymousAuth) { status = SMBServerConnect(*outConnection, NULL, netfsOptions, kSMBAuthTypeAnonymous); if (NT_SUCCESS(status)) { goto authDone; } } authDone: if (!NT_SUCCESS(status)) { goto done; } if (options & kSMBOptionSessionOnly) { goto done; } /* * If the target doesn't contain a share name, let's assume that the * caller means IPC$, unless a share name is required. */ if (!((struct smb_ctx *)hContext)->ct_origshare) { err = smb_ctx_setshare(hContext, "IPC$"); if (err) { if (err == ENAMETOOLONG) { status = STATUS_NAME_TOO_LONG; } else { status = STATUS_NO_MEMORY; } errno = err; goto done; } } /* OK, now we have a virtual circuit but no tree connection yet. */ err = smb_share_connect((*outConnection)->context); if (err) { status = STATUS_BAD_NETWORK_NAME; errno = err; goto done; } status = STATUS_SUCCESS; done: if (netfsOptions) { CFRelease(netfsOptions); } if (ServerParams) { CFRelease(ServerParams); } if ((!NT_SUCCESS(status)) && *outConnection) { SMBReleaseServer(*outConnection); *outConnection = NULL; } return status; }