Esempio n. 1
0
File: netfs.c Progetto: B1NG0/cifs
/*
 * SMBNetFsTreeConnectForEnumerateShares
 *
 * When enumerating shares we need a IPC$ tree connection. This is really only 
 * need by the old RAP calls, since the DCE/RPC code will create a whole new
 * session.
 */
int32_t
SMBNetFsTreeConnectForEnumerateShares(SMBHANDLE inConnection)
{
	int error = 0;
    void *hContext = NULL;
	
	SMBServerContext(inConnection, &hContext);
	error = smb_ctx_setshare(hContext, "IPC$");
	if (!error) {
		error = smb_share_connect(hContext);
	}
	return error;
}
Esempio n. 2
0
int
cmd_view(int argc, char *argv[])
{
	struct smb_ctx sctx, *ctx = &sctx;
	struct smb_share_info_1 *rpbuf, *ep;
	char *cp;
	u_int16_t type;
	int error, opt, bufsize, i, entries, total;
	

	if (argc < 2)
		view_usage();
	if (smb_ctx_init(ctx, argc, argv, SMBL_VC, SMBL_VC, SMB_ST_ANY) != 0)
		exit(1);
	if (smb_ctx_readrc(ctx) != 0)
		exit(1);
	if (smb_rc)
		rc_close(smb_rc);
	while ((opt = getopt(argc, argv, STDPARAM_OPT)) != EOF) {
		switch(opt){
		    case STDPARAM_ARGS:
			error = smb_ctx_opt(ctx, opt, optarg);
			if (error)
				exit(1);
			break;
		    default:
			view_usage();
			/*NOTREACHED*/
		}
	}
#ifdef APPLE
	if (loadsmbvfs())
		errx(EX_OSERR, "SMB filesystem is not available");
#endif
	smb_ctx_setshare(ctx, "IPC$", SMB_ST_ANY);
	if (smb_ctx_resolve(ctx) != 0)
		exit(1);
	error = smb_ctx_lookup(ctx, SMBL_SHARE, SMBLK_CREATE);
	if (error) {
		smb_error("could not login to server %s", error, ctx->ct_ssn.ioc_srvname);
		exit(1);
	}
	printf("Share        Type       Comment\n");
	printf("-------------------------------\n");
	bufsize = 0xffe0; /* samba notes win2k bug with 65535 */
	rpbuf = malloc(bufsize);
	error = smb_rap_NetShareEnum(ctx, 1, rpbuf, bufsize, &entries, &total);
	if (error &&
	    error != (SMB_ERROR_MORE_DATA | SMB_RAP_ERROR)) {
		smb_error("unable to list resources", error);
		exit(1);
	}
	for (ep = rpbuf, i = 0; i < entries; i++, ep++) {
		type = letohs(ep->shi1_type);

		cp = (char*)rpbuf + ep->shi1_remark;
		printf("%-12s %-10s %s\n", ep->shi1_netname,
		    shtype[min(type, sizeof shtype / sizeof(char *) - 1)],
		    ep->shi1_remark ? nls_str_toloc(cp, cp) : "");
	}
	printf("\n%d shares listed from %d available\n", entries, total);
	free(rpbuf);
	return 0;
}
Esempio n. 3
0
File: server.c Progetto: B1NG0/cifs
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;
}
Esempio n. 4
0
File: server.c Progetto: B1NG0/cifs
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;
}
Esempio n. 5
0
File: server.c Progetto: B1NG0/cifs
NTSTATUS
SMBMountShareEx(
	SMBHANDLE	inConnection,
	const char	*targetShare,
	const char	*mountPoint,
	unsigned	mountFlags,
	uint64_t	mountOptions,
	mode_t 		fileMode,
	mode_t 		dirMode,
	void (*callout)(void  *, void *), 
	void *args)
{
    NTSTATUS    status = STATUS_SUCCESS;
    int         err = 0;
    void *      hContext = NULL;
	CFStringRef mountPtRef = NULL;
	CFMutableDictionaryRef mOptions = NULL;
	CFNumberRef numRef = NULL;
	
	status = SMBServerContext(inConnection, &hContext);
	if (!NT_SUCCESS(status)) {
		/* Couldn't get the context? */
        goto done;
    }

	mOptions = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, 
										 &kCFTypeDictionaryValueCallBacks);
	if (mOptions == NULL) {
		/* Couldn't create the mount option dictionary, error out */
		errno = ENOMEM;
		status = STATUS_NO_MEMORY;
        goto done;
	}
	
	numRef = CFNumberCreate (NULL, kCFNumberSInt32Type, &mountFlags);
	if (numRef) {
		/* Put the mount flags into the dictionary */
		CFDictionarySetValue (mOptions, kNetFSMountFlagsKey, numRef);
		CFRelease(numRef);
	}
	
	if (mountOptions & kSMBMntOptionNoStreams) {
		/* Don't use NTFS Streams even if they are supported by the server.  */
		CFDictionarySetValue (mOptions, kStreamstMountKey, kCFBooleanFalse);
	}
		
	if (mountOptions & kSMBMntOptionNoNotifcations) {
		/* Don't use Remote Notifications even if they are supported by the server. */
		CFDictionarySetValue (mOptions, kNotifyOffMountKey, kCFBooleanTrue);
	}
		
	if (mountOptions & kSMBMntOptionSoftMount) {
		/* Mount the volume soft, return time out error durring reconnect. */
		CFDictionarySetValue (mOptions, kNetFSSoftMountKey, kCFBooleanTrue);
	}
	
	if (mountOptions & kSMBReservedTMMount) {
		/* Mount the volume as a Time Machine mount. */
		CFDictionarySetValue (mOptions, kTimeMachineMountKey, kCFBooleanTrue);
	}

	/*
	 * Specify permissions that should be assigned to files and directories. The 
	 * value must be specified as an octal numbers. A value of zero means use the
	 * default values. Not setting these in the dictionary will force the default
	 * values to be used.
	 */
	if (fileMode || dirMode) {		
		if (fileMode) {
			numRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt16Type, &fileMode);
			if (numRef) {
				CFDictionarySetValue (mOptions, kfileModeKey, numRef);
				CFRelease(numRef);
			}
		}
		if (dirMode) {
			numRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt16Type, &dirMode);
			if (numRef) {
				CFDictionarySetValue (mOptions, kdirModeKey, numRef);
				CFRelease(numRef);
			}
		}
	}
	
	/* Get the mount point */
	if (mountPoint) {
		mountPtRef = CFStringCreateWithCString(kCFAllocatorDefault, mountPoint, 
											   kCFStringEncodingUTF8);
	}
	if (mountPtRef == NULL) {
		/* No mount point */
		errno = ENOMEM;
		status = STATUS_NO_MEMORY;
		goto done;
	}
	/* Set the share if they gave us one */
	if (targetShare) {
		err = smb_ctx_setshare(hContext, targetShare);
	}
	
	if (err == 0) {
		err = smb_mount(hContext, mountPtRef, mOptions, NULL, callout, args);
	}
	
	if (err) {
		errno = err;
		status = STATUS_UNSUCCESSFUL;
		goto done;
	}
	
done:
	if (mOptions) {
		CFRelease(mOptions);
	}
	if (mountPtRef) {
		CFRelease(mountPtRef);
	}
	return status;
}
Esempio n. 6
0
/*
 * Here we expect something like "[proto:]//[user@]host[/share][/path]"
 */
int
smb_ctx_parseunc(struct smb_ctx *ctx, const char *unc, int sharetype,
	const char **next)
{
	const char *p = unc;
	char *p1;
	char tmp[1024];
	int error ;

	ctx->ct_parsedlevel = SMBL_NONE;
	if (*p++ != '/' || *p++ != '/') {
		smb_error("UNC should start with '//'", 0);
		return EINVAL;
	}
	p1 = tmp;
	error = getsubstring(p, '@', p1, sizeof(tmp), &p);
	if (!error) {
		if (ctx->ct_maxlevel < SMBL_VC) {
			smb_error("no user name required", 0);
			return EINVAL;
		}
		if (*p1 == 0) {
			smb_error("empty user name", 0);
			return EINVAL;
		}
		error = smb_ctx_setuser(ctx, tmp);
		if (error)
			return error;
		ctx->ct_parsedlevel = SMBL_VC;
	}
	error = getsubstring(p, '/', p1, sizeof(tmp), &p);
	if (error) {
		error = getsubstring(p, '\0', p1, sizeof(tmp), &p);
		if (error) {
			smb_error("no server name found", 0);
			return error;
		}
	}
	if (*p1 == 0) {
		smb_error("empty server name", 0);
		return EINVAL;
	}
	error = smb_ctx_setserver(ctx, tmp);
	if (error)
		return error;
	if (sharetype == SMB_ST_NONE) {
		*next = p;
		return 0;
	}
	if (*p != 0 && ctx->ct_maxlevel < SMBL_SHARE) {
		smb_error("no share name required", 0);
		return EINVAL;
	}
	error = getsubstring(p, '/', p1, sizeof(tmp), &p);
	if (error) {
		error = getsubstring(p, '\0', p1, sizeof(tmp), &p);
		if (error) {
			smb_error("unexpected end of line", 0);
			return error;
		}
	}
	if (*p1 == 0 && ctx->ct_minlevel >= SMBL_SHARE) {
		smb_error("empty share name", 0);
		return EINVAL;
	}
	*next = p;
	if (*p1 == 0)
		return 0;
	error = smb_ctx_setshare(ctx, p1, sharetype);
	return error;
}
Esempio n. 7
0
/*
 * Setup a new SMB client context.
 *
 * Get the SMB server's configuration stuff and
 * store it in the new client context object.
 */
int
smbrdr_ctx_new(struct smb_ctx **ctx_p, char *server,
	char *domain, char *user)
{
	struct smb_ctx *ctx = NULL;
	uchar_t nthash[SMBAUTH_HASH_SZ];
	int64_t lmcl;
	int authflags, err;

	assert(server != NULL);
	assert(domain != NULL);
	assert(user != NULL);

	if ((err = smb_ctx_alloc(&ctx)) != 0)
		return (NT_STATUS_NO_MEMORY);

	/*
	 * Set server, share, domain, user
	 * (in the ctx handle).
	 */
	(void) smb_ctx_setfullserver(ctx, server);
	(void) smb_ctx_setshare(ctx, "IPC$", USE_IPC);
	(void) smb_ctx_setdomain(ctx, domain, B_TRUE);
	(void) smb_ctx_setuser(ctx, user, B_TRUE);

	/*
	 * Set auth. info (hash) and type.
	 */
	if (user[0] == '\0') {
		authflags = SMB_AT_ANON;
	} else {
		(void) smb_config_getnum(SMB_CI_LM_LEVEL, &lmcl);
		if (lmcl <= 2) {
			/* Send NTLM */
			authflags = SMB_AT_NTLM1;
		} else {
			/* Send NTLMv2 */
			authflags = SMB_AT_NTLM2;
		}
		smb_ipc_get_passwd(nthash, sizeof (nthash));
		(void) smb_ctx_setpwhash(ctx, nthash, NULL);
	}
	(void) smb_ctx_setauthflags(ctx, authflags);

	/*
	 * Do lookup, connect, session setup, tree connect.
	 * Or find and reuse a session/tree, if one exists.
	 */
	if ((err = smb_ctx_resolve(ctx)) != 0) {
		err = NT_STATUS_BAD_NETWORK_PATH;
		goto errout;
	}
	if ((err = smb_ctx_get_ssn(ctx)) != 0) {
		err = NT_STATUS_NETWORK_ACCESS_DENIED;
		goto errout;
	}
	if ((err = smb_ctx_get_tree(ctx)) != 0) {
		err = NT_STATUS_BAD_NETWORK_NAME;
		goto errout;
	}

	/* Success! */
	*ctx_p = ctx;
	return (0);

errout:
	smb_ctx_free(ctx);
	return (err);
}
Esempio n. 8
0
int
cmd_view(int argc, char *argv[])
{
	struct smb_ctx *ctx;
	int error, err2, opt;

	if (argc < 2)
		view_usage();

	error = smb_ctx_alloc(&ctx);
	if (error)
		return (error);

	error = smb_ctx_scan_argv(ctx, argc, argv,
	    SMBL_SERVER, SMBL_SERVER, USE_WILDCARD);
	if (error)
		return (error);

	error = smb_ctx_readrc(ctx);
	if (error)
		return (error);

	while ((opt = getopt(argc, argv, STDPARAM_OPT)) != EOF) {
		if (opt == '?')
			view_usage();
		error = smb_ctx_opt(ctx, opt, optarg);
		if (error)
			return (error);
	}

	smb_ctx_setshare(ctx, "IPC$", USE_IPC);

	/*
	 * Resolve the server address,
	 * setup derived defaults.
	 */
	error = smb_ctx_resolve(ctx);
	if (error)
		return (error);

	/*
	 * Have server, share, etc. from above:
	 * smb_ctx_scan_argv, option settings.
	 * Get the session and tree.
	 */
again:
	error = smb_ctx_get_ssn(ctx);
	if (error == EAUTH) {
		err2 = smb_get_authentication(ctx);
		if (err2 == 0)
			goto again;
	}
	if (error) {
		smb_error(gettext("//%s: login failed"),
		    error, ctx->ct_fullserver);
		return (error);
	}

	error = smb_ctx_get_tree(ctx);
	if (error) {
		smb_error(gettext("//%s/%s: tree connect failed"),
		    error, ctx->ct_fullserver, ctx->ct_origshare);
		return (error);
	}

	/*
	 * Have IPC$ tcon, now list shares.
	 * This prints its own errors.
	 */
	error = enum_shares(ctx);
	if (error)
		return (error);

	smb_ctx_free(ctx);
	return (0);
}
Esempio n. 9
0
/*
 * Here we expect something like "[proto:]//[user@]host[:psmb[:pnb]][/share][/path]"
 */
int
smb_ctx_parseunc(struct smb_ctx *ctx, const char *unc, int sharetype,
	const char **next)
{
	const char *p = unc;
	char *p1, *psmb, *pnb;
	char tmp[1024];
	int error ;

	ctx->ct_parsedlevel = SMBL_NONE;
	if (*p++ != '/' || *p++ != '/') {
		smb_error("UNC should start with '//'", 0);
		return EINVAL;
	}
	p1 = tmp;
	error = getsubstring(p, '@', p1, sizeof(tmp), &p);
	if (!error) {
		if (ctx->ct_maxlevel < SMBL_VC) {
			smb_error("no user name required", 0);
			return EINVAL;
		}
		if (*p1 == 0) {
			smb_error("empty user name", 0);
			return EINVAL;
		}
		error = smb_ctx_setuser(ctx, tmp);
		if (error)
			return error;
		ctx->ct_parsedlevel = SMBL_VC;
	}
	error = getsubstring(p, '/', p1, sizeof(tmp), &p);
	if (error) {
		error = getsubstring(p, '\0', p1, sizeof(tmp), &p);
		if (error) {
			smb_error("no server name found", 0);
			return error;
		}
	}
	if (*p1 == 0) {
		smb_error("empty server name", 0);
		return EINVAL;
	}
	/*
	 * Check for port number specification.
	 */
	psmb = strchr(tmp, ':');
	if (psmb) {
		*psmb++ = '\0';
		pnb = strchr(psmb, ':');
		if (pnb) {
			*pnb++ = '\0';
			error = smb_ctx_setnbport(ctx, atoi(pnb));
			if (error) {
				smb_error("Invalid NetBIOS port number", 0);
				return error;
			}
		}
		error = smb_ctx_setsmbport(ctx, atoi(psmb));
		if (error) {
			smb_error("Invalid SMB port number", 0);
			return error;
		}
	}
	error = smb_ctx_setserver(ctx, tmp);
	if (error)
		return error;
	if (sharetype == SMB_ST_NONE) {
		*next = p;
		return 0;
	}
	if (*p != 0 && ctx->ct_maxlevel < SMBL_SHARE) {
		smb_error("no share name required", 0);
		return EINVAL;
	}
	error = getsubstring(p, '/', p1, sizeof(tmp), &p);
	if (error) {
		error = getsubstring(p, '\0', p1, sizeof(tmp), &p);
		if (error) {
			smb_error("unexpected end of line", 0);
			return error;
		}
	}
	if (*p1 == 0 && ctx->ct_minlevel >= SMBL_SHARE) {
		smb_error("empty share name", 0);
		return EINVAL;
	}
	*next = p;
	if (*p1 == 0)
		return 0;
	error = smb_ctx_setshare(ctx, p1, sharetype);
	return error;
}