/*
 * smbrdr_logon
 *
 * I'm not sure this really needs to do anything, but for now
 * let's go ahead and authenticate here so this can return a
 * status reflecting the outcome of authentication.
 *
 * If this successfully builds an smb_ctx, it just frees it.
 * The driver retains sessions for a little while after the
 * last reference goes away, so the session created here will
 * usually still exist when the next call to smbrdr_ctx_new
 * asks for this server+user (immediately after this returns),
 * and only one session setup will go over the wire.
 */
int
smbrdr_logon(char *srv, char *dom, char *user)
{
	struct smb_ctx *ctx;
	int err;

	err = smbrdr_ctx_new(&ctx, srv, dom, user);
	if (err == 0)
		smb_ctx_free(ctx);
	return (err);
}
Exemple #2
0
/*
 * Try making a connection with the server described by
 * the info in the smb_iod_ssn_t arg.  If successful,
 * start an IOD thread to service it, then return to
 * the client side of the door.
 */
int
iod_newvc(smb_iod_ssn_t *clnt_ssn)
{
	smb_ctx_t *ctx;
	thread_t tid;
	int err;


	/*
	 * This needs to essentially "clone" the smb_ctx_t
	 * from the client side of the door, or at least
	 * as much of it as we need while creating a VC.
	 */
	err = smb_ctx_alloc(&ctx);
	if (err)
		return (err);
	bcopy(clnt_ssn, &ctx->ct_iod_ssn, sizeof (ctx->ct_iod_ssn));

	/*
	 * Do the initial connection setup here, so we can
	 * report the outcome to the door client.
	 */
	err = smb_iod_connect(ctx);
	if (err != 0)
		goto out;

	/*
	 * Create the driver session now, so we don't
	 * race with the door client findvc call.
	 */
	if ((err = smb_ctx_gethandle(ctx)) != 0)
		goto out;
	if (ioctl(ctx->ct_dev_fd, SMBIOC_SSN_CREATE, &ctx->ct_ssn) < 0) {
		err = errno;
		goto out;
	}

	/* The rest happens in the iod_work thread. */
	err = thr_create(NULL, 0, iod_work, ctx, THR_DETACHED, &tid);
	if (err == 0) {
		/*
		 * Given to the new thread.
		 * free at end of iod_work
		 */
		ctx = NULL;
	}

out:
	if (ctx)
		smb_ctx_free(ctx);

	return (err);
}
Exemple #3
0
/*
 * Be the reader thread for some VC.
 *
 * This is started by a door call thread, which means
 * this is always at least the 2nd thread, therefore
 * it should never see thr_count==0 or terminating.
 */
void *
iod_work(void *arg)
{
	smb_ctx_t *ctx = arg;

	mutex_lock(&iod_mutex);
	if (iod_thr_count++ == 0) {
		alarm(0);
		DPRINT("iod_work: cancelled alarm\n");
	}
	mutex_unlock(&iod_mutex);

	(void) smb_iod_work(ctx);

	mutex_lock(&iod_mutex);
	if (--iod_thr_count == 0) {
		DPRINT("iod_work: schedule alarm\n");
		alarm(ALARM_TIME);
	}
	mutex_unlock(&iod_mutex);

	smb_ctx_free(ctx);
	return (NULL);
}
Exemple #4
0
int
cmd_discon(int argc, char *argv[])
{
	struct smb_ctx *ctx;
	int error, opt;

	if (argc < 2)
		discon_usage();

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

	error = smb_ctx_scan_argv(ctx, argc, argv,
	    SMBL_SERVER, SMBL_SERVER, USE_WILDCARD);
	if (error != 0)
		goto out;

	error = smb_ctx_readrc(ctx);
	if (error != 0)
		goto out;

	while ((opt = getopt(argc, argv, STDPARAM_OPT)) != EOF) {
		if (opt == '?')
			discon_usage();
		error = smb_ctx_opt(ctx, opt, optarg);
		if (error != 0)
			goto out;
	}

	/*
	 * Resolve the server address,
	 * setup derived defaults.
	 */
	error = smb_ctx_resolve(ctx);
	if (error != 0)
		goto out;

	/*
	 * Have server, user, etc. from above:
	 * smb_ctx_scan_argv, option settings.
	 *
	 * Lookup a session without creating.
	 * (First part of smb_ctx_get_ssn)
	 * If we find the session, kill it.
	 */
	error = smb_ctx_findvc(ctx);
	if (error == ENOENT) {
		/* Already gone. We're done. */
		if (smb_debug)
			fprintf(stderr, "session not found\n");
		error = 0;
		goto out;
	}
	if (error == 0) {
		/* Found session.  Kill it. */
		error = smb_ctx_kill(ctx);
	}

	if (error != 0) {
		smb_error(gettext("//%s: discon failed"),
		    error, ctx->ct_fullserver);
	}

out:
	smb_ctx_free(ctx);
	return (error);
}
void
smbrdr_ctx_free(struct smb_ctx *ctx)
{
	smb_ctx_free(ctx);
}
/*
 * 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);
}
Exemple #7
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);
}
Exemple #8
0
int
cmd_print(int argc, char *argv[])
{
	struct smb_ctx *ctx = NULL;
	char *filename;
	int error, opt;
	int file = -1;

	/* last arg is the print file. */
	if (argc < 3)
		print_usage();

	error = smb_ctx_alloc(&ctx);
	if (error)
		goto out;

	error = smb_ctx_scan_argv(ctx, argc-1, argv,
	    SMBL_SHARE, SMBL_SHARE, USE_SPOOLDEV);
	if (error)
		goto out;

	error = smb_ctx_readrc(ctx);
	if (error)
		goto out;

	while ((opt = getopt(argc-1, argv, STDPARAM_OPT)) != EOF) {
		if (opt == '?')
			print_usage();
		error = smb_ctx_opt(ctx, opt, optarg);
		if (error)
			goto out;
	}
	if (optind != argc-2)
		print_usage();
	filename = argv[argc-1];

	if (strcmp(filename, "-") == 0) {
		file = 0;	/* stdin */
		filename = "stdin";
	} else {
		file = open(filename, O_RDONLY, 0);
		if (file < 0) {
			smb_error("could not open file %s\n", errno, filename);
			exit(1);
		}
	}

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

	/*
	 * Have server + share names, options etc.
	 * Get the session and tree.
	 */
again:
	error = smb_ctx_get_ssn(ctx);
	if (error == EAUTH) {
		int err2 = smb_get_authentication(ctx);
		if (err2 == 0)
			goto again;
	}
	if (error) {
		smb_error(gettext("//%s: login failed"),
		    error, ctx->ct_fullserver);
		goto out;
	}

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

	/*
	 * Have the printer share connection.
	 * Print the file.
	 */
	snprintf(titlebuf, sizeof (titlebuf), "%s %s",
	    ctx->ct_user, filename);

	error = print_file(ctx, titlebuf, file);


out:
	/* don't close stdin (file=0) */
	if (file > 0)
		close(file);

	smb_ctx_free(ctx);

	return (error);
}