Example #1
0
/*
 * smb_match_netlogon_seqnum
 *
 * A sequence number is associated with each machine password property
 * update and the netlogon credential chain setup. If the
 * sequence numbers don't match, a NETLOGON credential chain
 * establishment is required.
 *
 * Returns 0 if kpasswd_seqnum equals to netlogon_seqnum. Otherwise,
 * returns -1.
 */
boolean_t
smb_match_netlogon_seqnum(void)
{
	int64_t setpasswd_seqnum;
	int64_t netlogon_seqnum;

	(void) mutex_lock(&seqnum_mtx);
	(void) smb_config_getnum(SMB_CI_KPASSWD_SEQNUM, &setpasswd_seqnum);
	(void) smb_config_getnum(SMB_CI_NETLOGON_SEQNUM, &netlogon_seqnum);
	(void) mutex_unlock(&seqnum_mtx);
	return (setpasswd_seqnum == netlogon_seqnum);
}
Example #2
0
/*
 * smb_auth_validate_nt
 *
 * Validates given NTLM/NTLMv2 client response, passed in passwd arg, against
 * stored user's password, passed in smbpw
 *
 * If LM level <=4 server accepts NTLM/NTLMv2 responses, otherwise only NTLMv2
 */
boolean_t
smb_auth_validate_nt(
    unsigned char *challenge,
    uint32_t clen,
    smb_passwd_t *smbpw,
    unsigned char *passwd,
    int pwdlen,
    char *domain,
    char *username,
    uchar_t *session_key)
{
    int64_t lmlevel;
    boolean_t ok;

    if (smb_config_getnum(SMB_CI_LM_LEVEL, &lmlevel) != SMBD_SMF_OK)
        return (B_FALSE);

    if ((lmlevel == 5) && (pwdlen <= SMBAUTH_LM_RESP_SZ))
        return (B_FALSE);

    if (pwdlen > SMBAUTH_LM_RESP_SZ)
        ok = smb_ntlmv2_password_ok(challenge, clen,
                                    smbpw->pw_nthash, passwd, pwdlen,
                                    domain, username, session_key);
    else
        ok = smb_ntlm_password_ok(challenge, clen,
                                  smbpw->pw_nthash, passwd, session_key);

    return (ok);
}
Example #3
0
/*
 * smb_auth_validate_lm
 *
 * Validates given LM/LMv2 client response, passed in passwd arg, against
 * stored user's password, passed in smbpw
 *
 * If LM level <=3 server accepts LM responses, otherwise LMv2
 */
boolean_t
smb_auth_validate_lm(
    unsigned char *challenge,
    uint32_t clen,
    smb_passwd_t *smbpw,
    unsigned char *passwd,
    int pwdlen,
    char *domain,
    char *username)
{
    boolean_t ok = B_FALSE;
    int64_t lmlevel;

    if (pwdlen != SMBAUTH_LM_RESP_SZ)
        return (B_FALSE);

    if (smb_config_getnum(SMB_CI_LM_LEVEL, &lmlevel) != SMBD_SMF_OK)
        return (B_FALSE);

    if (lmlevel <= 3) {
        ok = smb_lm_password_ok(challenge, clen, smbpw->pw_lmhash,
                                passwd);
    }

    if (!ok)
        ok = smb_lmv2_password_ok(challenge, clen, smbpw->pw_nthash,
                                  passwd, domain, username);

    return (ok);
}
Example #4
0
/*
 * smb_update_netlogon_seqnum
 *
 * This function should only be called upon a successful netlogon
 * credential chain establishment to set the sequence number of the
 * netlogon to match with that of the kpasswd.
 */
void
smb_update_netlogon_seqnum(void)
{
	int64_t num;

	(void) mutex_lock(&seqnum_mtx);
	(void) smb_config_getnum(SMB_CI_KPASSWD_SEQNUM, &num);
	(void) smb_config_setnum(SMB_CI_NETLOGON_SEQNUM, num);
	(void) mutex_unlock(&seqnum_mtx);
}
Example #5
0
/*
 * smb_set_machine_passwd
 *
 * This function should be used when setting the machine password property.
 * The associated sequence number is incremented.
 */
static int
smb_set_machine_passwd(char *passwd)
{
	int64_t num;
	int rc = -1;

	if (smb_config_set(SMB_CI_MACHINE_PASSWD, passwd) != SMBD_SMF_OK)
		return (-1);

	(void) mutex_lock(&seqnum_mtx);
	(void) smb_config_getnum(SMB_CI_KPASSWD_SEQNUM, &num);
	if (smb_config_setnum(SMB_CI_KPASSWD_SEQNUM, ++num)
	    == SMBD_SMF_OK)
		rc = 0;
	(void) mutex_unlock(&seqnum_mtx);
	return (rc);
}
Example #6
0
/*
 * smb_pwd_update
 *
 * Updates the password entry of the given user if the user already
 * has an entry, otherwise it'll add an entry for the user with
 * given password and control information.
 */
static int
smb_pwd_update(const char *name, const char *password, int control)
{
	struct stat64 stbuf;
	FILE *src, *dst;
	int tempfd;
	int err = SMB_PWE_SUCCESS;
	smb_pwbuf_t pwbuf;
	smb_passwd_t smbpw;
	boolean_t newent = B_TRUE;
	boolean_t user_disable = B_FALSE;
	char uxbuf[1024];
	struct passwd uxpw;
	int64_t lm_level;

	err = smb_pwd_lock();
	if (err != SMB_PWE_SUCCESS)
		return (err);

	if (stat64(SMB_PASSWD, &stbuf) < 0) {
		err = SMB_PWE_STAT_FAILED;
		goto passwd_exit;
	}

	if ((tempfd = open(SMB_PASSTEMP, O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) {
		err = SMB_PWE_OPEN_FAILED;
		goto passwd_exit;
	}

	if ((dst = fdopen(tempfd, "wF")) == NULL) {
		err = SMB_PWE_OPEN_FAILED;
		goto passwd_exit;
	}

	if ((src = fopen(SMB_PASSWD, "rF")) == NULL) {
		err = SMB_PWE_OPEN_FAILED;
		(void) fclose(dst);
		(void) unlink(SMB_PASSTEMP);
		goto passwd_exit;
	}

	if (smb_config_getnum(SMB_CI_LM_LEVEL, &lm_level) != SMBD_SMF_OK)
		lm_level = 4;

	if (lm_level >= 4)
		control |= SMB_PWC_NOLM;

	pwbuf.pw_pwd = &smbpw;

	/*
	 * copy old password entries to temporary file while replacing
	 * the entry that matches "name"
	 */
	while (smb_pwd_fgetent(src, &pwbuf, SMB_PWD_GETF_ALL) != NULL) {
		if (strcmp(smbpw.pw_name, name) == 0) {
			err = smb_pwd_chgpwent(&smbpw, password, control);
			if (err == SMB_PWE_USER_DISABLE)
				user_disable = B_TRUE;
			err = smb_pwd_fputent(dst, &pwbuf);
			newent = B_FALSE;
		} else {
			err = smb_pwd_fputent(dst, &pwbuf);
		}

		if (err != SMB_PWE_SUCCESS) {
			(void) fclose(src);
			(void) fclose(dst);
			goto passwd_exit;
		}
	}

	if (newent) {
		if (getpwnam_r(name, &uxpw, uxbuf, sizeof (uxbuf))) {
			bzero(&smbpw, sizeof (smb_passwd_t));
			(void) strlcpy(smbpw.pw_name, uxpw.pw_name,
			    sizeof (smbpw.pw_name));
			smbpw.pw_uid = uxpw.pw_uid;
			(void) smb_pwd_chgpwent(&smbpw, password, control);
			err = smb_pwd_fputent(dst, &pwbuf);
		} else {
			err = SMB_PWE_USER_UNKNOWN;
		}

		if (err != SMB_PWE_SUCCESS) {
			(void) fclose(src);
			(void) fclose(dst);
			goto passwd_exit;
		}
	}

	(void) fclose(src);
	if (fclose(dst) != 0) {
		err = SMB_PWE_CLOSE_FAILED;
		goto passwd_exit; /* Don't trust the temporary file */
	}

	/* Rename temp to passwd */
	if (unlink(SMB_OPASSWD) && access(SMB_OPASSWD, 0) == 0) {
		err = SMB_PWE_UPDATE_FAILED;
		(void) unlink(SMB_PASSTEMP);
		goto passwd_exit;
	}

	if (link(SMB_PASSWD, SMB_OPASSWD) == -1) {
		err = SMB_PWE_UPDATE_FAILED;
		(void) unlink(SMB_PASSTEMP);
		goto passwd_exit;
	}

	if (rename(SMB_PASSTEMP, SMB_PASSWD) == -1) {
		err = SMB_PWE_UPDATE_FAILED;
		(void) unlink(SMB_PASSTEMP);
		goto passwd_exit;
	}

	(void) chmod(SMB_PASSWD, 0400);

passwd_exit:
	(void) smb_pwd_unlock();
	if ((err == SMB_PWE_SUCCESS) && user_disable)
		err = SMB_PWE_USER_DISABLE;

	return (err);
}
Example #7
0
/*
 * Some older clients (Windows 98) only handle the low byte
 * of the max workers value. If the low byte is less than
 * SMB_PI_MAX_WORKERS_MIN set it to SMB_PI_MAX_WORKERS_MIN.
 */
void
smb_load_kconfig(smb_kmod_cfg_t *kcfg)
{
	struct utsname uts;
	int64_t citem;
	int rc;

	bzero(kcfg, sizeof (smb_kmod_cfg_t));

	(void) smb_config_getnum(SMB_CI_MAX_WORKERS, &citem);
	kcfg->skc_maxworkers = (uint32_t)citem;
	if ((kcfg->skc_maxworkers & 0xFF) < SMB_PI_MAX_WORKERS_MIN) {
		kcfg->skc_maxworkers &= ~0xFF;
		kcfg->skc_maxworkers += SMB_PI_MAX_WORKERS_MIN;
	}

	(void) smb_config_getnum(SMB_CI_KEEPALIVE, &citem);
	kcfg->skc_keepalive = (uint32_t)citem;
	if ((kcfg->skc_keepalive != 0) &&
	    (kcfg->skc_keepalive < SMB_PI_KEEP_ALIVE_MIN))
		kcfg->skc_keepalive = SMB_PI_KEEP_ALIVE_MIN;

	(void) smb_config_getnum(SMB_CI_MAX_CONNECTIONS, &citem);
	kcfg->skc_maxconnections = (uint32_t)citem;
	kcfg->skc_restrict_anon = smb_config_getbool(SMB_CI_RESTRICT_ANON);
	kcfg->skc_signing_enable = smb_config_getbool(SMB_CI_SIGNING_ENABLE);
	kcfg->skc_signing_required = smb_config_getbool(SMB_CI_SIGNING_REQD);
	kcfg->skc_netbios_enable = smb_config_getbool(SMB_CI_NETBIOS_ENABLE);
	kcfg->skc_ipv6_enable = smb_config_getbool(SMB_CI_IPV6_ENABLE);
	kcfg->skc_print_enable = smb_config_getbool(SMB_CI_PRINT_ENABLE);
	kcfg->skc_oplock_enable = smb_config_getbool(SMB_CI_OPLOCK_ENABLE);
	kcfg->skc_sync_enable = smb_config_getbool(SMB_CI_SYNC_ENABLE);
	kcfg->skc_traverse_mounts = smb_config_getbool(SMB_CI_TRAVERSE_MOUNTS);
	kcfg->skc_max_protocol = smb_config_get_max_protocol();
	kcfg->skc_secmode = smb_config_get_secmode();

	rc = smb_config_getnum(SMB_CI_MAXIMUM_CREDITS, &citem);
	if (rc != SMBD_SMF_OK)
		citem = SMB_PI_MAX_CREDITS;
	if (citem < SMB_PI_MIN_CREDITS)
		citem = SMB_PI_MIN_CREDITS;
	if (citem > SMB_PI_MAX_CREDITS)
		citem = SMB_PI_MAX_CREDITS;
	kcfg->skc_maximum_credits = (uint16_t)citem;

	rc = smb_config_getnum(SMB_CI_INITIAL_CREDITS, &citem);
	if (rc != SMBD_SMF_OK)
		citem = SMB_PI_MIN_CREDITS;
	if (citem < SMB_PI_MIN_CREDITS)
		citem = SMB_PI_MIN_CREDITS;
	if (citem > kcfg->skc_maximum_credits)
		citem = kcfg->skc_maximum_credits;
	kcfg->skc_initial_credits = (uint16_t)citem;

	(void) smb_getdomainname(kcfg->skc_nbdomain,
	    sizeof (kcfg->skc_nbdomain));
	(void) smb_getfqdomainname(kcfg->skc_fqdn,
	    sizeof (kcfg->skc_fqdn));
	(void) smb_getnetbiosname(kcfg->skc_hostname,
	    sizeof (kcfg->skc_hostname));
	(void) smb_config_getstr(SMB_CI_SYS_CMNT, kcfg->skc_system_comment,
	    sizeof (kcfg->skc_system_comment));
	smb_config_get_version(&kcfg->skc_version);
	kcfg->skc_execflags = smb_config_get_execinfo(NULL, NULL, 0);
	if (smb_config_get_localuuid(kcfg->skc_machine_uuid) < 0) {
		syslog(LOG_ERR, "smb_load_kconfig: no machine_uuid");
		uuid_generate_time(kcfg->skc_machine_uuid);
	}
	/* skc_negtok, skc_negtok_len: see smbd_authsvc.c */

	(void) uname(&uts);
	(void) snprintf(kcfg->skc_native_os, sizeof (kcfg->skc_native_os),
	    "%s %s %s", uts.sysname, uts.release, uts.version);

	(void) strlcpy(kcfg->skc_native_lm, "Native SMB service",
	    sizeof (kcfg->skc_native_lm));
}
Example #8
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);
}