Example #1
0
File: server.c Project: B1NG0/cifs
/* Prompt for a password and set it on the SMB context. */
static Boolean
SMBPasswordPrompt(
    SMBHANDLE hConnection,
	uint64_t options)
{
    void *      hContext = NULL;
    NTSTATUS    status;
    char *      passwd;
    char        passbuf[SMB_MAXPASSWORDLEN + 1];
    char        prompt[128];

	/* They told us not to prompt */
	if (options & kSMBOptionNoPrompt)
		return false;

	status = SMBServerContext(hConnection, &hContext);
	if (!NT_SUCCESS(status)) {
        return false;
    }

    /* 
	 * If the password is already set, don't prompt. Since anonymous and guest
	 * both have an empty password this will protect us from prompting in
	 * those cases.
     */
	if (((struct smb_ctx *)hContext)->ct_flags & SMBCF_EXPLICITPWD) {
        return false;
    }

   /* 
	 * If the target hasn't set a user name, let's assume that we should use
     * the current username. This is almost always what the caller wants, when
	 * being prompted for a password. The above check protect us from overriding
	 * anonymouse connections.
     */
	if (((struct smb_ctx *)hContext)->ct_setup.ioc_user[0] == '\0') {
        struct passwd * pwent;
		
        pwent = getpwuid(geteuid());
        if (pwent) {
            smb_ctx_setuser(hContext, pwent->pw_name);
        }
    }
	
    snprintf(prompt, sizeof(prompt), "Password for %s: ",
            ((struct smb_ctx *)hContext)->serverName);

    /* If we have a TTY, read a password and retry ... */
    passwd = readpassphrase(prompt, passbuf, sizeof(passbuf), RPP_REQUIRE_TTY);
    if (passwd) {
        smb_ctx_setpassword(hContext, passwd, TRUE);
        memset(passbuf, 0, sizeof(passbuf));
    }
	return true;
}
Example #2
0
File: parse_url.c Project: aosm/smb
/* 
 * Need to call SetWorkgroupFromURL just in case we have a workgroup name. CFURL does not handle
 * a CIFS style URL with a workgroup name.
 */
static int SetUserNameFromURL(struct smb_ctx *ctx, CFURLRef url)
{
	CFStringRef userNameRef = SetWorkgroupFromURL(ctx, url);
	char username[SMB_MAXUSERNAMELEN+1];
	int error;

	/* No user name in the URL */
	if (! userNameRef)
		return 0;
	LogCFString(userNameRef, "Username",__FUNCTION__, __LINE__);

	/* Conversion failed or the data doesn't fit in the buffer */
	if (CFStringGetCString(userNameRef, username, SMB_MAXUSERNAMELEN+1, kCFStringEncodingUTF8) == FALSE) {
		error = ENAMETOOLONG; /* Not sure what else to return. */
	} else {
		error = smb_ctx_setuser(ctx, username);		
	}
	CFRelease(userNameRef);
	return error;
}
Example #3
0
File: server.c Project: 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;
}
Example #4
0
/*
 * Prescan command line for [-U user] argument
 * and fill context with defaults
 */
int
smb_ctx_init(struct smb_ctx *ctx, int argc, char *argv[],
	int minlevel, int maxlevel, int sharetype)
{
	int  opt, error = 0;
	uid_t euid;
	const char *arg, *cp;
	struct passwd *pwd;

	bzero(ctx,sizeof(*ctx));
	error = nb_ctx_create(&ctx->ct_nb);
	if (error)
		return error;
	ctx->ct_fd = -1;
	ctx->ct_parsedlevel = SMBL_NONE;
	ctx->ct_minlevel = minlevel;
	ctx->ct_maxlevel = maxlevel;

	ctx->ct_ssn.ioc_opt = SMBVOPT_CREATE;
	ctx->ct_ssn.ioc_timeout = 15;
	ctx->ct_ssn.ioc_retrycount = 4;
	ctx->ct_ssn.ioc_owner = SMBM_ANY_OWNER;
	ctx->ct_ssn.ioc_group = SMBM_ANY_GROUP;
	ctx->ct_ssn.ioc_mode = SMBM_EXEC;
	ctx->ct_ssn.ioc_rights = SMBM_DEFAULT;

	ctx->ct_sh.ioc_opt = SMBVOPT_CREATE;
	ctx->ct_sh.ioc_owner = SMBM_ANY_OWNER;
	ctx->ct_sh.ioc_group = SMBM_ANY_GROUP;
	ctx->ct_sh.ioc_mode = SMBM_EXEC;
	ctx->ct_sh.ioc_rights = SMBM_DEFAULT;
	ctx->ct_sh.ioc_owner = SMBM_ANY_OWNER;
	ctx->ct_sh.ioc_group = SMBM_ANY_GROUP;

	nb_ctx_setscope(ctx->ct_nb, "");
	euid = geteuid();
	if ((pwd = getpwuid(euid)) != NULL) {
		smb_ctx_setuser(ctx, pwd->pw_name);
		endpwent();
	} else if (euid == 0)
		smb_ctx_setuser(ctx, "root");
	else
		return 0;
	if (argv == NULL)
		return 0;
	for (opt = 1; opt < argc; opt++) {
		cp = argv[opt];
		if (strncmp(cp, "//", 2) != 0)
			continue;
		error = smb_ctx_parseunc(ctx, cp, sharetype, (const char**)&cp);
		if (error)
			return error;
		ctx->ct_uncnext = cp;
		break;
	}
	while (error == 0 && (opt = cf_getopt(argc, argv, ":E:L:U:")) != -1) {
		arg = cf_optarg;
		switch (opt) {
		    case 'E':
			error = smb_ctx_setcharset(ctx, arg);
			if (error)
				return error;
			break;
		    case 'L':
			error = nls_setlocale(optarg);
			if (error)
				break;
			break;
		    case 'U':
			error = smb_ctx_setuser(ctx, arg);
			break;
		}
	}
	cf_optind = cf_optreset = 1;
	return error;
}
Example #5
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;
}
Example #6
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);
}
Example #7
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;
}