Ejemplo n.º 1
0
bool torture_libnetapi_init_context(struct torture_context *tctx,
				    struct libnetapi_ctx **ctx_p)
{
	NET_API_STATUS status;
	struct libnetapi_ctx *ctx;
	TALLOC_CTX *frame = talloc_stackframe();

	if (!lp_load_global(lpcfg_configfile(tctx->lp_ctx))) {
		fprintf(stderr, "error loading %s\n", lpcfg_configfile(tctx->lp_ctx));
		talloc_free(frame);
		return W_ERROR_V(WERR_GENERAL_FAILURE);
	}

	init_names();
	load_interfaces();

	status = libnetapi_net_init(&ctx);
	if (status != 0) {
		talloc_free(frame);
		return false;
	}

	libnetapi_set_username(ctx,
		cli_credentials_get_username(cmdline_credentials));
	libnetapi_set_password(ctx,
		cli_credentials_get_password(cmdline_credentials));

	*ctx_p = ctx;

	talloc_free(frame);
	return true;
}
Ejemplo n.º 2
0
/**
 * Obtain the password, in the form MD4(unicode(password)) for this credentials context.
 *
 * Sometimes we only have this much of the password, while the rest of
 * the time this call avoids calling E_md4hash themselves.
 *
 * @param cred credentials context
 * @retval If set, the cleartext password, otherwise NULL
 */
_PUBLIC_ struct samr_Password *cli_credentials_get_nt_hash(struct cli_credentials *cred,
							   TALLOC_CTX *mem_ctx)
{
	const char *password = NULL;

	if (cred->nt_hash != NULL) {
		struct samr_Password *nt_hash = talloc(mem_ctx, struct samr_Password);
		if (!nt_hash) {
			return NULL;
		}

		*nt_hash = *cred->nt_hash;

		return nt_hash;
	}

	password = cli_credentials_get_password(cred);
	if (password) {
		struct samr_Password *nt_hash = talloc(mem_ctx, struct samr_Password);
		if (!nt_hash) {
			return NULL;
		}

		E_md4hash(password, nt_hash->hash);

		return nt_hash;
	}

	return NULL;
}
Ejemplo n.º 3
0
static NTSTATUS gensec_ntlmssp3_client_start(struct gensec_security *gensec_security)
{
	NTSTATUS nt_status;
	struct gensec_ntlmssp_context *gensec_ntlmssp;
	const char *user, *domain;
	const char *password;

	nt_status = gensec_ntlmssp_start(gensec_security);
	NT_STATUS_NOT_OK_RETURN(nt_status);

	gensec_ntlmssp =
		talloc_get_type_abort(gensec_security->private_data,
				      struct gensec_ntlmssp_context);

	nt_status = ntlmssp_client_start(gensec_ntlmssp,
					 lp_netbios_name(), lp_workgroup(),
					 lp_client_ntlmv2_auth(), &gensec_ntlmssp->ntlmssp_state);
	if (!NT_STATUS_IS_OK(nt_status)) {
		return nt_status;
	}

	cli_credentials_get_ntlm_username_domain(gensec_security->credentials, gensec_ntlmssp, &user, &domain);
	if (!user || !domain) {
		return NT_STATUS_NO_MEMORY;
	}

	nt_status = ntlmssp_set_username(gensec_ntlmssp->ntlmssp_state, user);
	if (!NT_STATUS_IS_OK(nt_status)) {
		return nt_status;
	}

	nt_status = ntlmssp_set_domain(gensec_ntlmssp->ntlmssp_state, domain);
	if (!NT_STATUS_IS_OK(nt_status)) {
		return nt_status;
	}

	password = cli_credentials_get_password(gensec_security->credentials);
	if (!password) {
		return NT_STATUS_NO_MEMORY;
	}

	nt_status = ntlmssp_set_password(gensec_ntlmssp->ntlmssp_state, password);
	if (!NT_STATUS_IS_OK(nt_status)) {
		return nt_status;
	}

	if (gensec_ntlmssp->gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {
		gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
	}
	if (gensec_ntlmssp->gensec_security->want_features & GENSEC_FEATURE_SIGN) {
		gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
	}
	if (gensec_ntlmssp->gensec_security->want_features & GENSEC_FEATURE_SEAL) {
		gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
		gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
	}

	return NT_STATUS_OK;
}
Ejemplo n.º 4
0
/*
  old style session setup (pre NT1 protocol level)
*/
static NTSTATUS session_setup_old(struct composite_context *c,
				  struct smbcli_session *session, 
				  struct smb_composite_sesssetup *io,
				  struct smbcli_request **req) 
{
	NTSTATUS nt_status;
	struct sesssetup_state *state = talloc_get_type(c->private_data, struct sesssetup_state);
	const char *password = cli_credentials_get_password(io->in.credentials);
	DATA_BLOB names_blob = NTLMv2_generate_names_blob(state, session->transport->socket->hostname, cli_credentials_get_domain(io->in.credentials));
	DATA_BLOB session_key;
	int flags = 0;
	if (session->options.lanman_auth) {
		flags |= CLI_CRED_LANMAN_AUTH;
	}

	if (session->options.ntlmv2_auth) {
		flags |= CLI_CRED_NTLMv2_AUTH;
	}

	state->setup.old.level      = RAW_SESSSETUP_OLD;
	state->setup.old.in.bufsize = session->transport->options.max_xmit;
	state->setup.old.in.mpx_max = session->transport->options.max_mux;
	state->setup.old.in.vc_num  = 1;
	state->setup.old.in.sesskey = io->in.sesskey;
	state->setup.old.in.os      = "Unix";
	state->setup.old.in.lanman  = talloc_asprintf(state, "Samba %s", SAMBA_VERSION_STRING);
	cli_credentials_get_ntlm_username_domain(io->in.credentials, state, 
						 &state->setup.old.in.user,
						 &state->setup.old.in.domain);
	
	if (session->transport->negotiate.sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) {
		nt_status = cli_credentials_get_ntlm_response(io->in.credentials, state, 
							      &flags, 
							      session->transport->negotiate.secblob, 
							      names_blob,
							      &state->setup.old.in.password,
							      NULL,
							      NULL, &session_key);
		NT_STATUS_NOT_OK_RETURN(nt_status);
		set_user_session_key(session, &session_key);
		
		data_blob_free(&session_key);
	} else if (session->options.plaintext_auth) {
		state->setup.old.in.password = data_blob_talloc(state, password, strlen(password));
	} else {
		/* could match windows client and return 'cannot logon from this workstation', but it just confuses everybody */
		return NT_STATUS_INVALID_PARAMETER;
	}
	
	*req = smb_raw_sesssetup_send(session, &state->setup);
	if (!*req) {
		return NT_STATUS_NO_MEMORY;
	}
	return (*req)->status;
}
Ejemplo n.º 5
0
static bool test_parse_string(struct torture_context *tctx)
{
	struct cli_credentials *creds = cli_credentials_init_anon(tctx);

	/* anonymous */
	cli_credentials_parse_string(creds, "%", CRED_SPECIFIED);

	torture_assert_str_equal(tctx, cli_credentials_get_domain(creds),
				 "", "domain");

	torture_assert_str_equal(tctx, cli_credentials_get_username(creds),
				 "", "username");

	torture_assert(tctx, cli_credentials_get_password(creds) == NULL,
				 "password");

	/* username + password */
	cli_credentials_parse_string(creds, "somebody%secret", 
				     CRED_SPECIFIED);

	torture_assert_str_equal(tctx, cli_credentials_get_domain(creds),
				 "", "domain");

	torture_assert_str_equal(tctx, cli_credentials_get_username(creds),
				 "somebody", "username");

	torture_assert_str_equal(tctx, cli_credentials_get_password(creds),
				 "secret", "password");

	/* principal */
	cli_credentials_parse_string(creds, "prin@styx", 
				     CRED_SPECIFIED);

	torture_assert_str_equal(tctx, cli_credentials_get_realm(creds),
				 "STYX", "realm");

	torture_assert_str_equal(tctx, 
				 cli_credentials_get_principal(creds, tctx),
				 "prin@styx", "principal");

	return true;
}
Ejemplo n.º 6
0
static bool test_init_anonymous(struct torture_context *tctx)
{
	struct cli_credentials *creds = cli_credentials_init_anon(tctx);

	torture_assert_str_equal(tctx, cli_credentials_get_domain(creds),
				 "", "domain");

	torture_assert_str_equal(tctx, cli_credentials_get_username(creds),
				 "", "username");

	torture_assert(tctx, cli_credentials_get_password(creds) == NULL,
				 "password");

	return true;
}
Ejemplo n.º 7
0
static int net_password_change(struct net_context *ctx, int argc, const char **argv)
{
	NTSTATUS status;
	struct libnet_context *libnetctx;
	union libnet_ChangePassword r;
	char *password_prompt = NULL;
	const char *new_password;

	if (argc > 0 && argv[0]) {
		new_password = argv[0];
	} else {
		password_prompt = talloc_asprintf(ctx, "Enter new password for account [%s\\%s]:", 
							cli_credentials_get_domain(ctx->credentials), 
							cli_credentials_get_username(ctx->credentials));
		new_password = getpass(password_prompt);
	}

	libnetctx = libnet_context_init(ctx->event_ctx, ctx->lp_ctx);
	if (!libnetctx) {
		return -1;	
	}
	libnetctx->cred = ctx->credentials;

	/* prepare password change */
	r.generic.level			= LIBNET_CHANGE_PASSWORD_GENERIC;
	r.generic.in.account_name	= cli_credentials_get_username(ctx->credentials);
	r.generic.in.domain_name	= cli_credentials_get_domain(ctx->credentials);
	r.generic.in.oldpassword	= cli_credentials_get_password(ctx->credentials);
	r.generic.in.newpassword	= new_password;

	/* do password change */
	status = libnet_ChangePassword(libnetctx, ctx, &r);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("net_password_change: %s\n",r.generic.out.error_string));
		return -1;
	}

	talloc_free(libnetctx);

	return 0;
}
Ejemplo n.º 8
0
static bool test_init(struct torture_context *tctx)
{
	struct cli_credentials *creds = cli_credentials_init(tctx);

	cli_credentials_set_domain(creds, "bla", CRED_SPECIFIED);

	torture_assert_str_equal(tctx, "BLA", cli_credentials_get_domain(creds),
				 "domain");

	cli_credentials_set_username(creds, "someuser", CRED_SPECIFIED);

	torture_assert_str_equal(tctx, "someuser", 
				 cli_credentials_get_username(creds), 
				 "username");

	cli_credentials_set_password(creds, "p4ssw0rd", CRED_SPECIFIED);

	torture_assert_str_equal(tctx, "p4ssw0rd", 
				 cli_credentials_get_password(creds),
				 "password");

	return true;
}
Ejemplo n.º 9
0
static bool torture_krb5_as_req_creds(struct torture_context *tctx,
				      struct cli_credentials *credentials,
				      enum torture_krb5_test test)
{
	krb5_error_code k5ret;
	bool ok;
	krb5_creds my_creds;
	krb5_principal principal;
	struct smb_krb5_context *smb_krb5_context;
	enum credentials_obtained obtained;
	const char *error_string;
	const char *password = cli_credentials_get_password(credentials);
	krb5_get_init_creds_opt *krb_options = NULL;
	
	ok = torture_krb5_init_context(tctx, test, &smb_krb5_context);
	torture_assert(tctx, ok, "torture_krb5_init_context failed");
	
	k5ret = principal_from_credentials(tctx, credentials, smb_krb5_context,
					   &principal, &obtained,  &error_string);
	torture_assert_int_equal(tctx, k5ret, 0, error_string);

	switch (test)
	{
	case TORTURE_KRB5_TEST_PLAIN:
		break;

	case TORTURE_KRB5_TEST_PAC_REQUEST:
		torture_assert_int_equal(tctx,
					 krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context, &krb_options),
					 0, "krb5_get_init_creds_opt_alloc failed");
		
		torture_assert_int_equal(tctx,
					 krb5_get_init_creds_opt_set_pac_request(smb_krb5_context->krb5_context, krb_options, true),
					 0, "krb5_get_init_creds_opt_set_pac_request failed");
		break;
		
	case TORTURE_KRB5_TEST_BREAK_PW:
		password = "******";
		break;

	case TORTURE_KRB5_TEST_CLOCK_SKEW:
		torture_assert_int_equal(tctx,
					 krb5_set_real_time(smb_krb5_context->krb5_context, time(NULL) + 3600, 0),
					 0, "krb5_set_real_time failed");
		break;

	break;
	}
	k5ret = krb5_get_init_creds_password(smb_krb5_context->krb5_context, &my_creds, principal,
					     password, NULL, NULL, 0,
					     NULL, krb_options);
	krb5_get_init_creds_opt_free(smb_krb5_context->krb5_context, krb_options);
	
	switch (test)
	{
	case TORTURE_KRB5_TEST_PLAIN:
	case TORTURE_KRB5_TEST_PAC_REQUEST:
		torture_assert_int_equal(tctx, k5ret, 0, "krb5_get_init_creds_password failed");
		break;

	case TORTURE_KRB5_TEST_BREAK_PW:
		torture_assert_int_equal(tctx, k5ret, KRB5KDC_ERR_PREAUTH_FAILED, "krb5_get_init_creds_password should have failed");
		return true;

	case TORTURE_KRB5_TEST_CLOCK_SKEW:
		torture_assert_int_equal(tctx, k5ret, KRB5KRB_AP_ERR_SKEW, "krb5_get_init_creds_password should have failed");
		return true;

	}

	k5ret = krb5_free_cred_contents(smb_krb5_context->krb5_context, &my_creds);
	torture_assert_int_equal(tctx, k5ret, 0, "krb5_free_creds failed");

	return true;
}
Ejemplo n.º 10
0
/* Get the keytab (actually, a container containing the krb5_keytab)
 * attached to this context.  If this hasn't been done or set before,
 * it will be generated from the password.
 */
_PUBLIC_ int cli_credentials_get_keytab(struct cli_credentials *cred, 
					struct loadparm_context *lp_ctx,
					struct keytab_container **_ktc)
{
	krb5_error_code ret;
	struct keytab_container *ktc;
	struct smb_krb5_context *smb_krb5_context;
	const char *keytab_name;
	krb5_keytab keytab;
	TALLOC_CTX *mem_ctx;

	if (cred->keytab_obtained >= (MAX(cred->principal_obtained, 
					  cred->username_obtained))) {
		*_ktc = cred->keytab;
		return 0;
	}

	if (cli_credentials_is_anonymous(cred)) {
		return EINVAL;
	}

	ret = cli_credentials_get_krb5_context(cred, lp_ctx,
					       &smb_krb5_context);
	if (ret) {
		return ret;
	}

	mem_ctx = talloc_new(cred);
	if (!mem_ctx) {
		return ENOMEM;
	}

	ret = smb_krb5_create_memory_keytab(mem_ctx,
					smb_krb5_context->krb5_context,
					cli_credentials_get_password(cred),
					cli_credentials_get_username(cred),
					cli_credentials_get_realm(cred),
					cli_credentials_get_kvno(cred),
					&keytab, &keytab_name);
	if (ret) {
		talloc_free(mem_ctx);
		return ret;
	}

	ret = smb_krb5_get_keytab_container(mem_ctx, smb_krb5_context,
					    keytab, keytab_name, &ktc);
	if (ret) {
		talloc_free(mem_ctx);
		return ret;
	}

	cred->keytab_obtained = (MAX(cred->principal_obtained, 
				     cred->username_obtained));

	/* We make this keytab up based on a password.  Therefore
	 * match-by-key is acceptable, we can't match on the wrong
	 * principal */
	ktc->password_based = true;

	talloc_steal(cred, ktc);
	cred->keytab = ktc;
	*_ktc = cred->keytab;
	talloc_free(mem_ctx);
	return ret;
}
Ejemplo n.º 11
0
static bool test_wbc_logon_user(struct torture_context *tctx)
{
    struct wbcLogonUserParams params;
    struct wbcLogonUserInfo *info = NULL;
    struct wbcAuthErrorInfo *error = NULL;
    struct wbcUserPasswordPolicyInfo *policy = NULL;
    struct wbcInterfaceDetails *iface;
    struct wbcDomainSid sid;
    enum wbcSidType sidtype;
    char *sidstr;
    wbcErr ret;

    ZERO_STRUCT(params);

    ret = wbcLogonUser(&params, &info, &error, &policy);
    torture_assert_wbc_equal(tctx, ret, WBC_ERR_INVALID_PARAM,
                             "%s", "wbcLogonUser succeeded for NULL where it should "
                             "have failed");

    params.username = cli_credentials_get_username(cmdline_credentials);
    params.password = cli_credentials_get_password(cmdline_credentials);

    ret = wbcAddNamedBlob(&params.num_blobs, &params.blobs,
                          "foo", 0, discard_const_p(uint8_t, "bar"), 4);
    torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
                             "%s", "wbcAddNamedBlob failed");

    ret = wbcLogonUser(&params, &info, &error, &policy);
    torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
                             "wbcLogonUser for %s failed", params.username);
    wbcFreeMemory(info);
    info = NULL;
    wbcFreeMemory(error);
    error = NULL;
    wbcFreeMemory(policy);
    policy = NULL;

    params.password = "******";

    ret = wbcLogonUser(&params, &info, &error, &policy);
    torture_assert_wbc_equal(tctx, ret, WBC_ERR_AUTH_ERROR,
                             "wbcLogonUser for %s should have failed with "
                             "WBC_ERR_AUTH_ERROR", params.username);
    wbcFreeMemory(info);
    info = NULL;
    wbcFreeMemory(error);
    error = NULL;
    wbcFreeMemory(policy);
    policy = NULL;

    ret = wbcAddNamedBlob(&params.num_blobs, &params.blobs,
                          "membership_of", 0,
                          discard_const_p(uint8_t, "S-1-2-3-4"),
                          strlen("S-1-2-3-4")+1);
    torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
                             "%s", "wbcAddNamedBlob failed");
    params.password = cli_credentials_get_password(cmdline_credentials);
    ret = wbcLogonUser(&params, &info, &error, &policy);
    torture_assert_wbc_equal(tctx, ret, WBC_ERR_AUTH_ERROR,
                             "wbcLogonUser for %s should have failed with "
                             "WBC_ERR_AUTH_ERROR", params.username);
    wbcFreeMemory(info);
    info = NULL;
    wbcFreeMemory(error);
    error = NULL;
    wbcFreeMemory(policy);
    policy = NULL;
    wbcFreeMemory(params.blobs);
    params.blobs = NULL;
    params.num_blobs = 0;

    ret = wbcInterfaceDetails(&iface);
    torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
                             "%s", "wbcInterfaceDetails failed");

    ret = wbcLookupName(iface->netbios_domain, cli_credentials_get_username(cmdline_credentials), &sid,
                        &sidtype);
    wbcFreeMemory(iface);
    torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
                             "wbcLookupName for %s failed", cli_credentials_get_username(cmdline_credentials));

    ret = wbcSidToString(&sid, &sidstr);
    torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
                             "%s", "wbcSidToString failed");

    ret = wbcAddNamedBlob(&params.num_blobs, &params.blobs,
                          "membership_of", 0,
                          (uint8_t *)sidstr, strlen(sidstr)+1);
    torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
                             "%s", "wbcAddNamedBlob failed");
    wbcFreeMemory(sidstr);
    params.password = cli_credentials_get_password(cmdline_credentials);
    ret = wbcLogonUser(&params, &info, &error, &policy);
    torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
                             "wbcLogonUser for %s failed", params.username);
    wbcFreeMemory(info);
    info = NULL;
    wbcFreeMemory(error);
    error = NULL;
    wbcFreeMemory(policy);
    policy = NULL;
    wbcFreeMemory(params.blobs);
    params.blobs = NULL;
    params.num_blobs = 0;

    return true;
}
Ejemplo n.º 12
0
static bool test_wbc_change_password(struct torture_context *tctx)
{
    wbcErr ret;
    const char *oldpass = cli_credentials_get_password(cmdline_credentials);
    const char *newpass = "******";

    struct samr_CryptPassword new_nt_password;
    struct samr_CryptPassword new_lm_password;
    struct samr_Password old_nt_hash_enc;
    struct samr_Password old_lanman_hash_enc;

    uint8_t old_nt_hash[16];
    uint8_t old_lanman_hash[16];
    uint8_t new_nt_hash[16];
    uint8_t new_lanman_hash[16];

    struct wbcChangePasswordParams params;

    if (oldpass == NULL) {
        torture_skip(tctx,
                     "skipping wbcChangeUserPassword test as old password cannot be retrieved\n");
    }

    ZERO_STRUCT(params);

    E_md4hash(oldpass, old_nt_hash);
    E_md4hash(newpass, new_nt_hash);

    if (lpcfg_client_lanman_auth(tctx->lp_ctx) &&
            E_deshash(newpass, new_lanman_hash) &&
            E_deshash(oldpass, old_lanman_hash)) {

        /* E_deshash returns false for 'long' passwords (> 14
           DOS chars).  This allows us to match Win2k, which
           does not store a LM hash for these passwords (which
           would reduce the effective password length to 14) */

        encode_pw_buffer(new_lm_password.data, newpass, STR_UNICODE);
        arcfour_crypt(new_lm_password.data, old_nt_hash, 516);
        E_old_pw_hash(new_nt_hash, old_lanman_hash,
                      old_lanman_hash_enc.hash);

        params.old_password.response.old_lm_hash_enc_length =
            sizeof(old_lanman_hash_enc.hash);
        params.old_password.response.old_lm_hash_enc_data =
            old_lanman_hash_enc.hash;
        params.new_password.response.lm_length =
            sizeof(new_lm_password.data);
        params.new_password.response.lm_data =
            new_lm_password.data;
    } else {
        ZERO_STRUCT(new_lm_password);
        ZERO_STRUCT(old_lanman_hash_enc);
    }

    encode_pw_buffer(new_nt_password.data, newpass, STR_UNICODE);

    arcfour_crypt(new_nt_password.data, old_nt_hash, 516);
    E_old_pw_hash(new_nt_hash, old_nt_hash, old_nt_hash_enc.hash);

    params.old_password.response.old_nt_hash_enc_length =
        sizeof(old_nt_hash_enc.hash);
    params.old_password.response.old_nt_hash_enc_data =
        old_nt_hash_enc.hash;
    params.new_password.response.nt_length = sizeof(new_nt_password.data);
    params.new_password.response.nt_data = new_nt_password.data;

    params.level = WBC_CHANGE_PASSWORD_LEVEL_RESPONSE;
    params.account_name = cli_credentials_get_username(cmdline_credentials);
    params.domain_name = cli_credentials_get_domain(cmdline_credentials);

    ret = wbcChangeUserPasswordEx(&params, NULL, NULL, NULL);
    torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
                             "wbcChangeUserPassword for %s failed", params.account_name);

    if (!test_wbc_authenticate_user_int(tctx, newpass)) {
        return false;
    }

    ret = wbcChangeUserPassword(cli_credentials_get_username(cmdline_credentials), newpass,
                                cli_credentials_get_password(cmdline_credentials));
    torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
                             "wbcChangeUserPassword for %s failed", params.account_name);

    return test_wbc_authenticate_user_int(tctx, cli_credentials_get_password(cmdline_credentials));
}
Ejemplo n.º 13
0
/* Get the keytab (actually, a container containing the krb5_keytab)
 * attached to this context.  If this hasn't been done or set before,
 * it will be generated from the password.
 */
_PUBLIC_ int cli_credentials_get_keytab(struct cli_credentials *cred, 
					struct loadparm_context *lp_ctx,
					struct keytab_container **_ktc)
{
	krb5_error_code ret;
	struct keytab_container *ktc;
	struct smb_krb5_context *smb_krb5_context;
	const char *keytab_name;
	krb5_keytab keytab;
	TALLOC_CTX *mem_ctx;
	const char *username = cli_credentials_get_username(cred);
	const char *realm = cli_credentials_get_realm(cred);
	const char *error_string;
	const char *salt_principal;

	if (cred->keytab_obtained >= (MAX(cred->principal_obtained, 
					  cred->username_obtained))) {
		*_ktc = cred->keytab;
		return 0;
	}

	if (cli_credentials_is_anonymous(cred)) {
		return EINVAL;
	}

	ret = cli_credentials_get_krb5_context(cred, lp_ctx,
					       &smb_krb5_context);
	if (ret) {
		return ret;
	}

	mem_ctx = talloc_new(cred);
	if (!mem_ctx) {
		return ENOMEM;
	}

	/*
	 * FIXME: Currently there is no better way than to create the correct
	 * salt principal by checking if the username ends with a '$'. It would
	 * be better if it is part of the credentials.
	 */
	ret = smb_krb5_create_salt_principal(mem_ctx,
					     username,
					     realm,
					     &salt_principal,
					     &error_string);
	if (ret) {
		talloc_free(mem_ctx);
		return ret;
	}

	ret = smb_krb5_create_memory_keytab(mem_ctx,
					    smb_krb5_context->krb5_context,
					    cli_credentials_get_password(cred),
					    username,
					    realm,
					    salt_principal,
					    cli_credentials_get_kvno(cred),
					    &keytab,
					    &keytab_name);
	if (ret) {
		talloc_free(mem_ctx);
		return ret;
	}

	ret = smb_krb5_get_keytab_container(mem_ctx, smb_krb5_context,
					    keytab, keytab_name, &ktc);
	if (ret) {
		talloc_free(mem_ctx);
		return ret;
	}

	cred->keytab_obtained = (MAX(cred->principal_obtained, 
				     cred->username_obtained));

	/* We make this keytab up based on a password.  Therefore
	 * match-by-key is acceptable, we can't match on the wrong
	 * principal */
	ktc->password_based = true;

	talloc_steal(cred, ktc);
	cred->keytab = ktc;
	*_ktc = cred->keytab;
	talloc_free(mem_ctx);
	return ret;
}
Ejemplo n.º 14
0
_PUBLIC_ NTSTATUS cli_credentials_get_ntlm_response(struct cli_credentials *cred, TALLOC_CTX *mem_ctx, 
					   int *flags,
					   DATA_BLOB challenge,
					   const NTTIME *server_timestamp,
					   DATA_BLOB target_info,
					   DATA_BLOB *_lm_response, DATA_BLOB *_nt_response, 
					   DATA_BLOB *_lm_session_key, DATA_BLOB *_session_key) 
{
	const char *user, *domain;
	DATA_BLOB lm_response, nt_response;
	DATA_BLOB lm_session_key, session_key;
	const struct samr_Password *nt_hash;
	lm_session_key = data_blob(NULL, 0);

	/* We may already have an NTLM response we prepared earlier.
	 * This is used for NTLM pass-though authentication */
	if (cred->nt_response.data || cred->lm_response.data) {
		*_nt_response = cred->nt_response;
		*_lm_response = cred->lm_response;

		if (!cred->lm_response.data) {
			*flags = *flags & ~CLI_CRED_LANMAN_AUTH;
		}
		*_lm_session_key = data_blob(NULL, 0);
		*_session_key = data_blob(NULL, 0);
		return NT_STATUS_OK;
	}

	nt_hash = cli_credentials_get_nt_hash(cred, mem_ctx);

	cli_credentials_get_ntlm_username_domain(cred, mem_ctx, &user, &domain);

	/* If we are sending a username@realm login (see function
	 * above), then we will not send LM, it will not be
	 * accepted */
	if (cred->principal_obtained > cred->username_obtained) {
		*flags = *flags & ~CLI_CRED_LANMAN_AUTH;
	}

	/* Likewise if we are a machine account (avoid protocol downgrade attacks) */
	if (cred->machine_account) {
		*flags = *flags & ~CLI_CRED_LANMAN_AUTH;
	}
	
	if (cred->use_kerberos == CRED_MUST_USE_KERBEROS) {
		return NT_STATUS_ACCESS_DENIED;
	}

	if (!nt_hash) {
		static const uint8_t zeros[16];
		/* do nothing - blobs are zero length */

		/* session key is all zeros */
		session_key = data_blob_talloc(mem_ctx, zeros, 16);
		lm_session_key = data_blob_talloc(mem_ctx, zeros, 16);

		lm_response = data_blob(NULL, 0);
		nt_response = data_blob(NULL, 0);
		
		/* not doing NTLM2 without a password */
		*flags &= ~CLI_CRED_NTLM2;
	} else if (*flags & CLI_CRED_NTLMv2_AUTH) {

		if (!target_info.length) {
			/* be lazy, match win2k - we can't do NTLMv2 without it */
			DEBUG(1, ("Server did not provide 'target information', required for NTLMv2\n"));
			return NT_STATUS_INVALID_PARAMETER;
		}

		/* TODO: if the remote server is standalone, then we should replace 'domain'
		   with the server name as supplied above */
		
		if (!SMBNTLMv2encrypt_hash(mem_ctx,
					   user, 
					   domain, 
					   nt_hash->hash, &challenge, 
					   server_timestamp, &target_info,
					   &lm_response, &nt_response, 
					   NULL, &session_key)) {
			return NT_STATUS_NO_MEMORY;
		}

		/* LM Key is incompatible... */
		*flags &= ~CLI_CRED_LANMAN_AUTH;
		if (lm_response.length != 0) {
			/*
			 * We should not expose the lm key.
			 */
			memset(lm_response.data, 0, lm_response.length);
		}
	} else if (*flags & CLI_CRED_NTLM2) {
		MD5_CTX md5_session_nonce_ctx;
		uint8_t session_nonce[16];
		uint8_t session_nonce_hash[16];
		uint8_t user_session_key[16];
		
		lm_response = data_blob_talloc(mem_ctx, NULL, 24);
		generate_random_buffer(lm_response.data, 8);
		memset(lm_response.data+8, 0, 16);

		memcpy(session_nonce, challenge.data, 8);
		memcpy(&session_nonce[8], lm_response.data, 8);
	
		MD5Init(&md5_session_nonce_ctx);
		MD5Update(&md5_session_nonce_ctx, challenge.data, 8);
		MD5Update(&md5_session_nonce_ctx, lm_response.data, 8);
		MD5Final(session_nonce_hash, &md5_session_nonce_ctx);

		DEBUG(5, ("NTLMSSP challenge set by NTLM2\n"));
		DEBUG(5, ("challenge is: \n"));
		dump_data(5, session_nonce_hash, 8);
		
		nt_response = data_blob_talloc(mem_ctx, NULL, 24);
		SMBOWFencrypt(nt_hash->hash,
			      session_nonce_hash,
			      nt_response.data);
		
		session_key = data_blob_talloc(mem_ctx, NULL, 16);

		SMBsesskeygen_ntv1(nt_hash->hash, user_session_key);
		hmac_md5(user_session_key, session_nonce, sizeof(session_nonce), session_key.data);
		dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);

		/* LM Key is incompatible... */
		*flags &= ~CLI_CRED_LANMAN_AUTH;
	} else {
		uint8_t lm_hash[16];
		nt_response = data_blob_talloc(mem_ctx, NULL, 24);
		SMBOWFencrypt(nt_hash->hash, challenge.data,
			      nt_response.data);
		
		session_key = data_blob_talloc(mem_ctx, NULL, 16);
		SMBsesskeygen_ntv1(nt_hash->hash, session_key.data);
		dump_data_pw("NT session key:\n", session_key.data, session_key.length);

		/* lanman auth is insecure, it may be disabled.  
		   We may also not have a password */
		if (*flags & CLI_CRED_LANMAN_AUTH) {
			const char *password;
			password = cli_credentials_get_password(cred);
			if (!password) {
				lm_response = nt_response;
			} else {
				lm_response = data_blob_talloc(mem_ctx, NULL, 24);
				if (!SMBencrypt(password,challenge.data,
						lm_response.data)) {
					/* If the LM password was too long (and therefore the LM hash being
					   of the first 14 chars only), don't send it.

					   We don't have any better options but to send the NT response 
					*/
					data_blob_free(&lm_response);
					lm_response = nt_response;
					/* LM Key is incompatible with 'long' passwords */
					*flags &= ~CLI_CRED_LANMAN_AUTH;
				} else if (E_deshash(password, lm_hash)) {
					lm_session_key = data_blob_talloc(mem_ctx, NULL, 16);
					memcpy(lm_session_key.data, lm_hash, 8);
					memset(&lm_session_key.data[8], '\0', 8);
					
					if (!(*flags & CLI_CRED_NTLM_AUTH)) {
						session_key = lm_session_key;
					}
				}
			}
		} else {
			const char *password;

			/* LM Key is incompatible... */
			lm_response = nt_response;
			*flags &= ~CLI_CRED_LANMAN_AUTH;

			password = cli_credentials_get_password(cred);
			if (password && E_deshash(password, lm_hash)) {
				lm_session_key = data_blob_talloc(mem_ctx, NULL, 16);
				memcpy(lm_session_key.data, lm_hash, 8);
				memset(&lm_session_key.data[8], '\0', 8);
			}
		}
	}
	if (_lm_response) {
		*_lm_response = lm_response;
	}
	if (_nt_response) {
		*_nt_response = nt_response;
	}
	if (_lm_session_key) {
		*_lm_session_key = lm_session_key;
	}
	if (_session_key) {
		*_session_key = session_key;
	}
	return NT_STATUS_OK;
}
Ejemplo n.º 15
0
static PyObject *py_creds_get_password(PyObject *self, PyObject *unused)
{
	return PyString_FromStringOrNULL(cli_credentials_get_password(PyCredentials_AsCliCredentials(self)));
}
Ejemplo n.º 16
0
/**
 * Fill in credentials for the machine trust account, from the
 * secrets.ldb or passed in handle to secrets.tdb (perhaps in CTDB).
 *
 * This version is used in parts of the code that can link in the
 * CTDB dbwrap backend, by passing down the already open handle.
 *
 * @param cred Credentials structure to fill in
 * @param db_ctx dbwrap context for secrets.tdb
 * @retval NTSTATUS error detailing any failure
 */
_PUBLIC_ NTSTATUS cli_credentials_set_machine_account_db_ctx(struct cli_credentials *cred,
							     struct loadparm_context *lp_ctx,
							     struct db_context *db_ctx)
{
	NTSTATUS status;
	char *filter;
	char *error_string = NULL;
	const char *domain;
	bool secrets_tdb_password_more_recent;
	time_t secrets_tdb_lct = 0;
	char *secrets_tdb_password = NULL;
	char *secrets_tdb_old_password = NULL;
	uint32_t secrets_tdb_secure_channel_type = SEC_CHAN_NULL;
	char *keystr;
	char *keystr_upper = NULL;
	TALLOC_CTX *tmp_ctx = talloc_named(cred, 0, "cli_credentials_set_secrets from ldb");
	if (!tmp_ctx) {
		return NT_STATUS_NO_MEMORY;
	}

	/* Bleh, nasty recursion issues: We are setting a machine
	 * account here, so we don't want the 'pending' flag around
	 * any more */
	cred->machine_account_pending = false;

	/* We have to do this, as the fallback in
	 * cli_credentials_set_secrets is to run as anonymous, so the domain is wiped */
	domain = cli_credentials_get_domain(cred);

	if (db_ctx) {
		TDB_DATA dbuf;
		keystr = talloc_asprintf(tmp_ctx, "%s/%s",
					 SECRETS_MACHINE_LAST_CHANGE_TIME,
					 domain);
		keystr_upper = strupper_talloc(tmp_ctx, keystr);
		status = dbwrap_fetch(db_ctx, tmp_ctx, string_tdb_data(keystr_upper),
				      &dbuf);
		if (NT_STATUS_IS_OK(status) && dbuf.dsize == 4) {
			secrets_tdb_lct = IVAL(dbuf.dptr,0);
		}

		keystr = talloc_asprintf(tmp_ctx, "%s/%s",
					 SECRETS_MACHINE_PASSWORD,
					 domain);
		keystr_upper = strupper_talloc(tmp_ctx, keystr);
		status = dbwrap_fetch(db_ctx, tmp_ctx, string_tdb_data(keystr_upper),
				      &dbuf);
		if (NT_STATUS_IS_OK(status)) {
			secrets_tdb_password = (char *)dbuf.dptr;
		}

		keystr = talloc_asprintf(tmp_ctx, "%s/%s",
					 SECRETS_MACHINE_PASSWORD_PREV,
					 domain);
		keystr_upper = strupper_talloc(tmp_ctx, keystr);
		status = dbwrap_fetch(db_ctx, tmp_ctx, string_tdb_data(keystr_upper),
				      &dbuf);
		if (NT_STATUS_IS_OK(status)) {
			secrets_tdb_old_password = (char *)dbuf.dptr;
		}

		keystr = talloc_asprintf(tmp_ctx, "%s/%s",
					 SECRETS_MACHINE_SEC_CHANNEL_TYPE,
					 domain);
		keystr_upper = strupper_talloc(tmp_ctx, keystr);
		status = dbwrap_fetch(db_ctx, tmp_ctx, string_tdb_data(keystr_upper),
				      &dbuf);
		if (NT_STATUS_IS_OK(status) && dbuf.dsize == 4) {
			secrets_tdb_secure_channel_type = IVAL(dbuf.dptr,0);
		}
	}

	filter = talloc_asprintf(cred, SECRETS_PRIMARY_DOMAIN_FILTER, 
				 domain);
	status = cli_credentials_set_secrets_lct(cred, lp_ctx, NULL,
						 SECRETS_PRIMARY_DOMAIN_DN,
						 filter, secrets_tdb_lct, secrets_tdb_password, &error_string);
	if (secrets_tdb_password == NULL) {
		secrets_tdb_password_more_recent = false;
	} else if (NT_STATUS_EQUAL(NT_STATUS_CANT_ACCESS_DOMAIN_INFO, status)
	    || NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, status)) {
		secrets_tdb_password_more_recent = true;
	} else if (secrets_tdb_lct > cli_credentials_get_password_last_changed_time(cred)) {
		secrets_tdb_password_more_recent = true;
	} else if (secrets_tdb_lct == cli_credentials_get_password_last_changed_time(cred)) {
		secrets_tdb_password_more_recent = strcmp(secrets_tdb_password, cli_credentials_get_password(cred)) != 0;
	} else {
		secrets_tdb_password_more_recent = false;
	}

	if (secrets_tdb_password_more_recent) {
		char *machine_account = talloc_asprintf(tmp_ctx, "%s$", lpcfg_netbios_name(lp_ctx));
		cli_credentials_set_password(cred, secrets_tdb_password, CRED_SPECIFIED);
		cli_credentials_set_old_password(cred, secrets_tdb_old_password, CRED_SPECIFIED);
		cli_credentials_set_domain(cred, domain, CRED_SPECIFIED);
		if (strequal(domain, lpcfg_workgroup(lp_ctx))) {
			cli_credentials_set_realm(cred, lpcfg_realm(lp_ctx), CRED_SPECIFIED);
		}
		cli_credentials_set_username(cred, machine_account, CRED_SPECIFIED);
		cli_credentials_set_password_last_changed_time(cred, secrets_tdb_lct);
		cli_credentials_set_secure_channel_type(cred, secrets_tdb_secure_channel_type);
		status = NT_STATUS_OK;
	} else if (!NT_STATUS_IS_OK(status)) {
		if (db_ctx) {
			error_string
				= talloc_asprintf(cred,
						  "Failed to fetch machine account password for %s from both "
						  "secrets.ldb (%s) and from %s",
						  domain,
						  error_string == NULL ? "error" : error_string,
						  dbwrap_name(db_ctx));
		} else {
			char *secrets_tdb_path;

			secrets_tdb_path = lpcfg_private_db_path(tmp_ctx,
								 lp_ctx,
								 "secrets");
			if (secrets_tdb_path == NULL) {
				return NT_STATUS_NO_MEMORY;
			}

			error_string = talloc_asprintf(cred,
						       "Failed to fetch machine account password from "
						       "secrets.ldb: %s and failed to open %s",
						       error_string == NULL ? "error" : error_string,
						       secrets_tdb_path);
		}
		DEBUG(1, ("Could not find machine account in secrets database: %s: %s\n",
			  error_string == NULL ? "error" : error_string,
			  nt_errstr(status)));
		/* set anonymous as the fallback, if the machine account won't work */
		cli_credentials_set_anonymous(cred);
	}

	TALLOC_FREE(tmp_ctx);
	return status;
}
Ejemplo n.º 17
0
 krb5_error_code kinit_to_ccache(TALLOC_CTX *parent_ctx,
				 struct cli_credentials *credentials,
				 struct smb_krb5_context *smb_krb5_context,
				 struct tevent_context *event_ctx,
				 krb5_ccache ccache,
				 enum credentials_obtained *obtained,
				 const char **error_string)
{
	krb5_error_code ret;
	const char *password;
#ifdef SAMBA4_USES_HEIMDAL
	const char *self_service;
#endif
	const char *target_service;
	time_t kdc_time = 0;
	krb5_principal princ;
	krb5_principal impersonate_principal;
	int tries;
	TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
	krb5_get_init_creds_opt *krb_options;

	if (!mem_ctx) {
		(*error_string) = strerror(ENOMEM);
		return ENOMEM;
	}

	ret = principal_from_credentials(mem_ctx, credentials, smb_krb5_context, &princ, obtained, error_string);
	if (ret) {
		talloc_free(mem_ctx);
		return ret;
	}

	if (princ == NULL) {
		(*error_string) = talloc_asprintf(credentials, "principal, username or realm was not specified in the credentials");
		talloc_free(mem_ctx);
		return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
	}

	ret = impersonate_principal_from_credentials(mem_ctx, credentials, smb_krb5_context, &impersonate_principal, error_string);
	if (ret) {
		talloc_free(mem_ctx);
		return ret;
	}

#ifdef SAMBA4_USES_HEIMDAL
	self_service = cli_credentials_get_self_service(credentials);
#endif
	target_service = cli_credentials_get_target_service(credentials);

	password = cli_credentials_get_password(credentials);

	/* setup the krb5 options we want */
	if ((ret = krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context, &krb_options))) {
		(*error_string) = talloc_asprintf(credentials, "krb5_get_init_creds_opt_alloc failed (%s)\n",
						  smb_get_krb5_error_message(smb_krb5_context->krb5_context,
									     ret, mem_ctx));
		talloc_free(mem_ctx);
		return ret;
	}

#ifdef SAMBA4_USES_HEIMDAL /* Disable for now MIT reads defaults when needed */
	/* get the defaults */
	krb5_get_init_creds_opt_set_default_flags(smb_krb5_context->krb5_context, NULL, NULL, krb_options);
#endif
	/* set if we want a forwardable ticket */
	switch (cli_credentials_get_krb_forwardable(credentials)) {
	case CRED_AUTO_KRB_FORWARDABLE:
		break;
	case CRED_NO_KRB_FORWARDABLE:
		krb5_get_init_creds_opt_set_forwardable(krb_options, FALSE);
		break;
	case CRED_FORCE_KRB_FORWARDABLE:
		krb5_get_init_creds_opt_set_forwardable(krb_options, TRUE);
		break;
	}

#ifdef SAMBA4_USES_HEIMDAL /* FIXME: MIT does not have this yet */
	/*
	 * In order to work against windows KDCs even if we use
	 * the netbios domain name as realm, we need to add the following
	 * flags:
	 * KRB5_INIT_CREDS_NO_C_CANON_CHECK;
	 * KRB5_INIT_CREDS_NO_C_NO_EKU_CHECK;
	 *
	 * On MIT: Set pkinit_eku_checking to none
	 */
	krb5_get_init_creds_opt_set_win2k(smb_krb5_context->krb5_context,
					  krb_options, true);
#else /* MIT */
	krb5_get_init_creds_opt_set_canonicalize(krb_options, true);
#endif

	tries = 2;
	while (tries--) {
#ifdef SAMBA4_USES_HEIMDAL
		struct tevent_context *previous_ev;
		/* Do this every time, in case we have weird recursive issues here */
		ret = smb_krb5_context_set_event_ctx(smb_krb5_context, event_ctx, &previous_ev);
		if (ret) {
			talloc_free(mem_ctx);
			return ret;
		}
#endif
		if (password) {
			if (impersonate_principal) {
#ifdef SAMBA4_USES_HEIMDAL
				ret = kerberos_kinit_s4u2_cc(
						smb_krb5_context->krb5_context,
						ccache, princ, password,
						impersonate_principal,
						self_service, target_service,
						krb_options, NULL, &kdc_time);
#else
				talloc_free(mem_ctx);
				(*error_string) = "INTERNAL error: s4u2 ops "
					"are not supported with MIT build yet";
				return EINVAL;
#endif
			} else {
				ret = kerberos_kinit_password_cc(
						smb_krb5_context->krb5_context,
						ccache, princ, password,
						target_service,
						krb_options, NULL, &kdc_time);
			}
		} else if (impersonate_principal) {
			talloc_free(mem_ctx);
			(*error_string) = "INTERNAL error: Cannot impersonate principal with just a keyblock.  A password must be specified in the credentials";
			return EINVAL;
		} else {
			/* No password available, try to use a keyblock instead */
			
			krb5_keyblock keyblock;
			const struct samr_Password *mach_pwd;
			mach_pwd = cli_credentials_get_nt_hash(credentials, mem_ctx);
			if (!mach_pwd) {
				talloc_free(mem_ctx);
				(*error_string) = "kinit_to_ccache: No password available for kinit\n";
				krb5_get_init_creds_opt_free(smb_krb5_context->krb5_context, krb_options);
#ifdef SAMBA4_USES_HEIMDAL
				smb_krb5_context_remove_event_ctx(smb_krb5_context, previous_ev, event_ctx);
#endif
				return EINVAL;
			}
			ret = smb_krb5_keyblock_init_contents(smb_krb5_context->krb5_context,
						 ENCTYPE_ARCFOUR_HMAC,
						 mach_pwd->hash, sizeof(mach_pwd->hash), 
						 &keyblock);
			
			if (ret == 0) {
				ret = kerberos_kinit_keyblock_cc(smb_krb5_context->krb5_context, ccache, 
								 princ, &keyblock,
								 target_service, krb_options,
								 NULL, &kdc_time);
				krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &keyblock);
			}
		}

#ifdef SAMBA4_USES_HEIMDAL
		smb_krb5_context_remove_event_ctx(smb_krb5_context, previous_ev, event_ctx);
#endif

		if (ret == KRB5KRB_AP_ERR_SKEW || ret == KRB5_KDCREP_SKEW) {
			/* Perhaps we have been given an invalid skew, so try again without it */
			time_t t = time(NULL);
			krb5_set_real_time(smb_krb5_context->krb5_context, t, 0);
		} else {
			/* not a skew problem */
			break;
		}
	}

	krb5_get_init_creds_opt_free(smb_krb5_context->krb5_context, krb_options);

	if (ret == KRB5KRB_AP_ERR_SKEW || ret == KRB5_KDCREP_SKEW) {
		(*error_string) = talloc_asprintf(credentials, "kinit for %s failed (%s)\n",
						  cli_credentials_get_principal(credentials, mem_ctx),
						  smb_get_krb5_error_message(smb_krb5_context->krb5_context,
									     ret, mem_ctx));
		talloc_free(mem_ctx);
		return ret;
	}

	/* cope with ticket being in the future due to clock skew */
	if ((unsigned)kdc_time > time(NULL)) {
		time_t t = time(NULL);
		int time_offset =(unsigned)kdc_time-t;
		DEBUG(4,("Advancing clock by %d seconds to cope with clock skew\n", time_offset));
		krb5_set_real_time(smb_krb5_context->krb5_context, t + time_offset + 1, 0);
	}
	
	if (ret == KRB5KDC_ERR_PREAUTH_FAILED && cli_credentials_wrong_password(credentials)) {
		ret = kinit_to_ccache(parent_ctx,
				      credentials,
				      smb_krb5_context,
				      event_ctx,
				      ccache, obtained,
				      error_string);
	}

	if (ret) {
		(*error_string) = talloc_asprintf(credentials, "kinit for %s failed (%s)\n",
						  cli_credentials_get_principal(credentials, mem_ctx),
						  smb_get_krb5_error_message(smb_krb5_context->krb5_context,
									     ret, mem_ctx));
		talloc_free(mem_ctx);
		return ret;
	}

	DEBUG(10,("kinit for %s succeeded\n",
		cli_credentials_get_principal(credentials, mem_ctx)));


	talloc_free(mem_ctx);
	return 0;
}
Ejemplo n.º 18
0
 krb5_error_code kinit_to_ccache(TALLOC_CTX *parent_ctx,
				 struct cli_credentials *credentials,
				 struct smb_krb5_context *smb_krb5_context,
				 krb5_ccache ccache) 
{
	krb5_error_code ret;
	const char *password;
	time_t kdc_time = 0;
	krb5_principal princ;
	int tries;
	TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);

	if (!mem_ctx) {
		return ENOMEM;
	}

	ret = principal_from_credentials(mem_ctx, credentials, smb_krb5_context, &princ);
	if (ret) {
		talloc_free(mem_ctx);
		return ret;
	}

	password = cli_credentials_get_password(credentials);

	tries = 2;
	while (tries--) {
		if (password) {
			ret = kerberos_kinit_password_cc(smb_krb5_context->krb5_context, ccache, 
							 princ, 
							 password, NULL, &kdc_time);
		} else {
			/* No password available, try to use a keyblock instead */
			
			krb5_keyblock keyblock;
			const struct samr_Password *mach_pwd;
			mach_pwd = cli_credentials_get_nt_hash(credentials, mem_ctx);
			if (!mach_pwd) {
				talloc_free(mem_ctx);
				DEBUG(1, ("kinit_to_ccache: No password available for kinit\n"));
				return EINVAL;
			}
			ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
						 ENCTYPE_ARCFOUR_HMAC,
						 mach_pwd->hash, sizeof(mach_pwd->hash), 
						 &keyblock);
			
			if (ret == 0) {
				ret = kerberos_kinit_keyblock_cc(smb_krb5_context->krb5_context, ccache, 
								 princ,
								 &keyblock, NULL, &kdc_time);
				krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &keyblock);
			}
		}

		if (ret == KRB5KRB_AP_ERR_SKEW || ret == KRB5_KDCREP_SKEW) {
			/* Perhaps we have been given an invalid skew, so try again without it */
			time_t t = time(NULL);
			krb5_set_real_time(smb_krb5_context->krb5_context, t, 0);
		} else {
			/* not a skew problem */
			break;
		}
	}

	if (ret == KRB5KRB_AP_ERR_SKEW || ret == KRB5_KDCREP_SKEW) {
		DEBUG(1,("kinit for %s failed (%s)\n", 
			 cli_credentials_get_principal(credentials, mem_ctx), 
			 smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
						    ret, mem_ctx)));
		talloc_free(mem_ctx);
		return ret;
	}

	/* cope with ticket being in the future due to clock skew */
	if ((unsigned)kdc_time > time(NULL)) {
		time_t t = time(NULL);
		int time_offset =(unsigned)kdc_time-t;
		DEBUG(4,("Advancing clock by %d seconds to cope with clock skew\n", time_offset));
		krb5_set_real_time(smb_krb5_context->krb5_context, t + time_offset + 1, 0);
	}
	
	if (ret == KRB5KDC_ERR_PREAUTH_FAILED && cli_credentials_wrong_password(credentials)) {
		ret = kinit_to_ccache(parent_ctx,
				      credentials,
				      smb_krb5_context,
				      ccache); 
	}
	if (ret) {
		DEBUG(1,("kinit for %s failed (%s)\n", 
			 cli_credentials_get_principal(credentials, mem_ctx), 
			 smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
						    ret, mem_ctx)));
		talloc_free(mem_ctx);
		return ret;
	} 
	talloc_free(mem_ctx);
	return 0;
}
Ejemplo n.º 19
0
/**
 * do reauth with wrong credentials,
 * hence triggering the error path in reauth.
 * The invalid reauth deletes the session.
 */
bool test_session_reauth6(struct torture_context *tctx, struct smb2_tree *tree)
{
	NTSTATUS status;
	TALLOC_CTX *mem_ctx = talloc_new(tctx);
	char fname[256];
	struct smb2_handle _h1;
	struct smb2_handle *h1 = NULL;
	struct smb2_create io1;
	bool ret = true;
	char *corrupted_password;
	struct cli_credentials *broken_creds;
	bool ok;
	bool encrypted;
	NTSTATUS expected;
	enum credentials_use_kerberos krb_state;

	krb_state = cli_credentials_get_kerberos_state(cmdline_credentials);
	if (krb_state == CRED_MUST_USE_KERBEROS) {
		torture_skip(tctx,
			     "Can't test failing session setup with kerberos.");
	}

	encrypted = smb2cli_tcon_is_encryption_on(tree->smbXcli);

	/* Add some random component to the file name. */
	snprintf(fname, 256, "session_reauth1_%s.dat",
		 generate_random_str(tctx, 8));

	smb2_util_unlink(tree, fname);

	smb2_oplock_create_share(&io1, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));
	io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;

	status = smb2_create(tree, mem_ctx, &io1);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h1 = io1.out.file.handle;
	h1 = &_h1;
	CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));

	/*
	 * reauthentication with invalid credentials:
	 */

	broken_creds = cli_credentials_shallow_copy(mem_ctx,
						    cmdline_credentials);
	torture_assert(tctx, (broken_creds != NULL), "talloc error");

	corrupted_password = talloc_asprintf(mem_ctx, "%s%s",
				cli_credentials_get_password(broken_creds),
				"corrupt");
	torture_assert(tctx, (corrupted_password != NULL), "talloc error");

	ok = cli_credentials_set_password(broken_creds, corrupted_password,
					  CRED_SPECIFIED);
	CHECK_VAL(ok, true);

	status = smb2_session_setup_spnego(tree->session,
					   broken_creds,
					   0 /* previous_session_id */);
	CHECK_STATUS(status, NT_STATUS_LOGON_FAILURE);

	torture_comment(tctx, "did failed reauth\n");
	/*
	 * now verify that the invalid session reauth has closed our session
	 */

	if (encrypted) {
		expected = NT_STATUS_CONNECTION_DISCONNECTED;
	} else {
		expected = NT_STATUS_USER_SESSION_DELETED;
	}

	smb2_oplock_create_share(&io1, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));

	status = smb2_create(tree, mem_ctx, &io1);
	CHECK_STATUS(status, expected);

done:
	if (h1 != NULL) {
		smb2_util_close(tree, *h1);
	}

	smb2_util_unlink(tree, fname);

	talloc_free(tree);

	talloc_free(mem_ctx);

	return ret;
}
Ejemplo n.º 20
0
static bool test_wbc_authenticate_user(struct torture_context *tctx)
{
    return test_wbc_authenticate_user_int(tctx, cli_credentials_get_password(cmdline_credentials));
}
Ejemplo n.º 21
0
static int create_keytab(TALLOC_CTX *parent_ctx,
			 struct cli_credentials *machine_account,
			 struct smb_krb5_context *smb_krb5_context,
			 const char **enctype_strings,
			 krb5_keytab keytab,
			 BOOL add_old) 
{
	krb5_error_code ret;
	const char *password_s;
	const char *old_secret;
	int kvno;
	krb5_principal salt_princ;
	krb5_principal princ;
	const char *princ_string;

	TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
	if (!mem_ctx) {
		return ENOMEM;
	}

	princ_string = cli_credentials_get_principal(machine_account, mem_ctx);
	/* Get the principal we will store the new keytab entries under */
	ret = principal_from_credentials(mem_ctx, machine_account, smb_krb5_context, &princ);
	if (ret) {
		DEBUG(1,("create_keytab: makeing krb5 principal failed (%s)\n",
			 smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
						    ret, mem_ctx)));
		talloc_free(mem_ctx);
		return ret;
	}

	/* The salt used to generate these entries may be different however, fetch that */
	ret = salt_principal_from_credentials(mem_ctx, machine_account, 
					      smb_krb5_context, 
					      &salt_princ);
	if (ret) {
		DEBUG(1,("create_keytab: makeing salt principal failed (%s)\n",
			 smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
						    ret, mem_ctx)));
		talloc_free(mem_ctx);
		return ret;
	}

	/* Finally, do the dance to get the password to put in the entry */
	password_s = cli_credentials_get_password(machine_account);
	if (!password_s) {
		krb5_keytab_entry entry;
		const struct samr_Password *mach_pwd;

		if (!str_list_check(enctype_strings, "arcfour-hmac-md5")) {
			DEBUG(1, ("Asked to create keytab, but with only an NT hash supplied, "
				  "but not listing arcfour-hmac-md5 as an enc type to include in the keytab!\n"));
			talloc_free(mem_ctx);
			return EINVAL;
		}

		/* If we don't have the plaintext password, try for
		 * the MD4 password hash */
		mach_pwd = cli_credentials_get_nt_hash(machine_account, mem_ctx);
		if (!mach_pwd) {
			/* OK, nothing to do here */
			talloc_free(mem_ctx);
			return 0;
		}
		ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
					 ETYPE_ARCFOUR_HMAC_MD5,
					 mach_pwd->hash, sizeof(mach_pwd->hash), 
					 &entry.keyblock);
		if (ret) {
			DEBUG(1, ("create_keytab: krb5_keyblock_init failed: %s\n",
				  smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
							     ret, mem_ctx)));
			talloc_free(mem_ctx);
			return ret;
		}

		entry.principal = princ;
		entry.vno       = cli_credentials_get_kvno(machine_account);
		ret = krb5_kt_add_entry(smb_krb5_context->krb5_context, keytab, &entry);
		if (ret) {
			DEBUG(1, ("Failed to add ARCFOUR_HMAC (only) entry for %s to keytab: %s",
				  cli_credentials_get_principal(machine_account, mem_ctx), 
				  smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
							     ret, mem_ctx)));
			talloc_free(mem_ctx);
			krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);
			return ret;
		}
		
		DEBUG(5, ("Added %s(kvno %d) to keytab (arcfour-hmac-md5)\n", 
			  cli_credentials_get_principal(machine_account, mem_ctx),
			  cli_credentials_get_kvno(machine_account)));

		krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);

		/* Can't go any further, we only have this one key */
		talloc_free(mem_ctx);
		return 0;
	}
	
	kvno = cli_credentials_get_kvno(machine_account);
	/* good, we actually have the real plaintext */
	ret = keytab_add_keys(mem_ctx, princ_string, princ, salt_princ, 
			      kvno, password_s, smb_krb5_context, 
			      enctype_strings, keytab);
	if (!ret) {
		talloc_free(mem_ctx);
		return ret;
	}

	if (!add_old || kvno == 0) {
		talloc_free(mem_ctx);
		return 0;
	}

	old_secret = cli_credentials_get_old_password(machine_account);
	if (!old_secret) {
		talloc_free(mem_ctx);
		return 0;
	}
	
	ret = keytab_add_keys(mem_ctx, princ_string, princ, salt_princ, 
			      kvno - 1, old_secret, smb_krb5_context, 
			      enctype_strings, keytab);
	if (!ret) {
		talloc_free(mem_ctx);
		return ret;
	}

	talloc_free(mem_ctx);
	return 0;
}
Ejemplo n.º 22
-1
/*
  send a nt1 style session setup
*/
static NTSTATUS session_setup_nt1(struct composite_context *c,
				  struct smbcli_session *session, 
				  struct smb_composite_sesssetup *io,
				  struct smbcli_request **req) 
{
	NTSTATUS nt_status = NT_STATUS_INTERNAL_ERROR;
	struct sesssetup_state *state = talloc_get_type(c->private_data,
							struct sesssetup_state);
	const char *domain = cli_credentials_get_domain(io->in.credentials);

	/*
	 * domain controllers tend to reject the NTLM v2 blob
	 * if the netbiosname is not valid (e.g. IP address or FQDN)
	 * so just leave it away (as Windows client do)
	 */
	DATA_BLOB names_blob = NTLMv2_generate_names_blob(state, NULL, domain);

	DATA_BLOB session_key = data_blob(NULL, 0);
	int flags = CLI_CRED_NTLM_AUTH;

	if (session->options.lanman_auth) {
		flags |= CLI_CRED_LANMAN_AUTH;
	}

	if (session->options.ntlmv2_auth) {
		flags |= CLI_CRED_NTLMv2_AUTH;
	}

	state->setup.nt1.level           = RAW_SESSSETUP_NT1;
	state->setup.nt1.in.bufsize      = session->transport->options.max_xmit;
	state->setup.nt1.in.mpx_max      = session->transport->options.max_mux;
	state->setup.nt1.in.vc_num       = 1;
	state->setup.nt1.in.sesskey      = io->in.sesskey;
	state->setup.nt1.in.capabilities = io->in.capabilities;
	state->setup.nt1.in.os           = "Unix";
	state->setup.nt1.in.lanman       = talloc_asprintf(state, "Samba %s", SAMBA_VERSION_STRING);

	cli_credentials_get_ntlm_username_domain(io->in.credentials, state, 
						 &state->setup.nt1.in.user,
						 &state->setup.nt1.in.domain);
	

	if (session->transport->negotiate.sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) {
		nt_status = cli_credentials_get_ntlm_response(io->in.credentials, state, 
							      &flags, 
							      session->transport->negotiate.secblob, 
							      names_blob,
							      &state->setup.nt1.in.password1,
							      &state->setup.nt1.in.password2,
							      NULL, &session_key);
		NT_STATUS_NOT_OK_RETURN(nt_status);
	} else if (session->options.plaintext_auth) {
		const char *password = cli_credentials_get_password(io->in.credentials);
		state->setup.nt1.in.password1 = data_blob_talloc(state, password, strlen(password));
		state->setup.nt1.in.password2 = data_blob(NULL, 0);
	} else {
		/* could match windows client and return 'cannot logon from this workstation', but it just confuses everybody */
		return NT_STATUS_INVALID_PARAMETER;
	}

	*req = smb_raw_sesssetup_send(session, &state->setup);
	if (!*req) {
		return NT_STATUS_NO_MEMORY;
	}

	if (NT_STATUS_IS_OK(nt_status)) {
		smb1cli_conn_activate_signing(session->transport->conn,
					      session_key,
					      state->setup.nt1.in.password2);

		nt_status = smb1cli_session_set_session_key(session->smbXcli,
							    session_key);
		data_blob_free(&session_key);
		if (!NT_STATUS_IS_OK(nt_status)) {
			return nt_status;
		}
	}

	return (*req)->status;
}