예제 #1
0
/**
 * Create a new credentials structure
 * @param mem_ctx TALLOC_CTX parent for credentials structure 
 */
struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx) 
{
	struct cli_credentials *cred = talloc(mem_ctx, struct cli_credentials);
	if (!cred) {
		return cred;
	}

	cred->netlogon_creds = NULL;
	cred->machine_account_pending = False;
	cred->workstation_obtained = CRED_UNINITIALISED;
	cred->username_obtained = CRED_UNINITIALISED;
	cred->password_obtained = CRED_UNINITIALISED;
	cred->domain_obtained = CRED_UNINITIALISED;
	cred->realm_obtained = CRED_UNINITIALISED;
	cred->ccache_obtained = CRED_UNINITIALISED;
	cred->client_gss_creds_obtained = CRED_UNINITIALISED;
	cred->server_gss_creds_obtained = CRED_UNINITIALISED;
	cred->keytab_obtained = CRED_UNINITIALISED;
	cred->principal_obtained = CRED_UNINITIALISED;

	cred->old_password = NULL;
	cred->smb_krb5_context = NULL;
	cred->salt_principal = NULL;
	cred->machine_account = False;

	cred->bind_dn = NULL;

	cred->tries = 3;
	cred->callback_running = False;

	cli_credentials_set_kerberos_state(cred, CRED_AUTO_USE_KERBEROS);

	return cred;
}
예제 #2
0
파일: credentials.c 프로젝트: GSam/samba
/**
 * Fill in a credentials structure as the anonymous user
 */
_PUBLIC_ void cli_credentials_set_anonymous(struct cli_credentials *cred) 
{
	cli_credentials_set_username(cred, "", CRED_SPECIFIED);
	cli_credentials_set_domain(cred, "", CRED_SPECIFIED);
	cli_credentials_set_password(cred, NULL, CRED_SPECIFIED);
	cli_credentials_set_realm(cred, NULL, CRED_SPECIFIED);
	cli_credentials_set_workstation(cred, "", CRED_UNINITIALISED);
	cli_credentials_set_kerberos_state(cred, CRED_DONT_USE_KERBEROS);
}
예제 #3
0
static PyObject *py_creds_set_kerberos_state(PyObject *self, PyObject *args)
{
	int state;
	if (!PyArg_ParseTuple(args, "i", &state))
		return NULL;

	cli_credentials_set_kerberos_state(PyCredentials_AsCliCredentials(self), state);
	Py_RETURN_NONE;
}
예제 #4
0
_PUBLIC_ void cli_credentials_set_impersonate_principal(struct cli_credentials *cred,
							const char *principal,
							const char *self_service)
{
	talloc_free(cred->impersonate_principal);
	cred->impersonate_principal = talloc_strdup(cred, principal);
	talloc_free(cred->self_service);
	cred->self_service = talloc_strdup(cred, self_service);
	cli_credentials_set_kerberos_state(cred, CRED_MUST_USE_KERBEROS);
}
예제 #5
0
파일: sasl.c 프로젝트: Alexander--/samba
/* 
   perform a LDAP/SASL/SPNEGO/{NTLMSSP,KRB5} bind (just how many layers can
   we fit on one socket??)
*/
static ADS_STATUS ads_sasl_spnego_gensec_bind(ADS_STRUCT *ads,
				const char *sasl,
				enum credentials_use_kerberos krb5_state,
				const char *target_service,
				const char *target_hostname,
				const DATA_BLOB server_blob)
{
	DATA_BLOB blob_in = data_blob_null;
	DATA_BLOB blob_out = data_blob_null;
	int rc;
	NTSTATUS nt_status;
	ADS_STATUS status;
	struct auth_generic_state *auth_generic_state;
	bool use_spnego_principal = lp_client_use_spnego_principal();
	const char *sasl_list[] = { sasl, NULL };
	NTTIME end_nt_time;
	struct ads_saslwrap *wrap = &ads->ldap_wrap_data;

	nt_status = auth_generic_client_prepare(NULL, &auth_generic_state);
	if (!NT_STATUS_IS_OK(nt_status)) {
		return ADS_ERROR_NT(nt_status);
	}

	if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_username(auth_generic_state, ads->auth.user_name))) {
		return ADS_ERROR_NT(nt_status);
	}
	if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_domain(auth_generic_state, ads->auth.realm))) {
		return ADS_ERROR_NT(nt_status);
	}
	if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_password(auth_generic_state, ads->auth.password))) {
		return ADS_ERROR_NT(nt_status);
	}

	if (server_blob.length == 0) {
		use_spnego_principal = false;
	}

	if (krb5_state == CRED_DONT_USE_KERBEROS) {
		use_spnego_principal = false;
	}

	cli_credentials_set_kerberos_state(auth_generic_state->credentials,
					   krb5_state);

	if (target_service != NULL) {
		nt_status = gensec_set_target_service(
					auth_generic_state->gensec_security,
					target_service);
		if (!NT_STATUS_IS_OK(nt_status)) {
			return ADS_ERROR_NT(nt_status);
		}
	}

	if (target_hostname != NULL) {
		nt_status = gensec_set_target_hostname(
					auth_generic_state->gensec_security,
					target_hostname);
		if (!NT_STATUS_IS_OK(nt_status)) {
			return ADS_ERROR_NT(nt_status);
		}
	}

	if (target_service != NULL && target_hostname != NULL) {
		use_spnego_principal = false;
	}

	switch (wrap->wrap_type) {
	case ADS_SASLWRAP_TYPE_SEAL:
		gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
		gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SEAL);
		break;
	case ADS_SASLWRAP_TYPE_SIGN:
		if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
			gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
		} else {
			/*
			 * windows servers are broken with sign only,
			 * so we let the NTLMSSP backend to seal here,
			 * via GENSEC_FEATURE_LDAP_STYLE.
			 */
			gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
			gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_LDAP_STYLE);
		}
		break;
	case ADS_SASLWRAP_TYPE_PLAIN:
		break;
	}

	nt_status = auth_generic_client_start_by_sasl(auth_generic_state,
						      sasl_list);
	if (!NT_STATUS_IS_OK(nt_status)) {
		return ADS_ERROR_NT(nt_status);
	}

	rc = LDAP_SASL_BIND_IN_PROGRESS;
	nt_status = NT_STATUS_MORE_PROCESSING_REQUIRED;
	if (use_spnego_principal) {
		blob_in = data_blob_dup_talloc(talloc_tos(), server_blob);
		if (blob_in.length == 0) {
			TALLOC_FREE(auth_generic_state);
			return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
		}
	} else {
		blob_in = data_blob_null;
	}
	blob_out = data_blob_null;

	while (true) {
		struct berval cred, *scred = NULL;

		nt_status = gensec_update(auth_generic_state->gensec_security,
					  talloc_tos(), blob_in, &blob_out);
		data_blob_free(&blob_in);
		if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)
		    && !NT_STATUS_IS_OK(nt_status))
		{
			TALLOC_FREE(auth_generic_state);
			data_blob_free(&blob_out);
			return ADS_ERROR_NT(nt_status);
		}

		if (NT_STATUS_IS_OK(nt_status) && rc == 0 && blob_out.length == 0) {
			break;
		}

		cred.bv_val = (char *)blob_out.data;
		cred.bv_len = blob_out.length;
		scred = NULL;
		rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, sasl, &cred, NULL, NULL, &scred);
		data_blob_free(&blob_out);
		if ((rc != LDAP_SASL_BIND_IN_PROGRESS) && (rc != 0)) {
			if (scred) {
				ber_bvfree(scred);
			}

			TALLOC_FREE(auth_generic_state);
			return ADS_ERROR(rc);
		}
		if (scred) {
			blob_in = data_blob_talloc(talloc_tos(),
						   scred->bv_val,
						   scred->bv_len);
			if (blob_in.length != scred->bv_len) {
				ber_bvfree(scred);
				TALLOC_FREE(auth_generic_state);
				return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
			}
			ber_bvfree(scred);
		} else {
			blob_in = data_blob_null;
		}
		if (NT_STATUS_IS_OK(nt_status) && rc == 0 && blob_in.length == 0) {
			break;
		}
	}

	data_blob_free(&blob_in);
	data_blob_free(&blob_out);

	if (wrap->wrap_type >= ADS_SASLWRAP_TYPE_SEAL) {
		bool ok;

		ok = gensec_have_feature(auth_generic_state->gensec_security,
					 GENSEC_FEATURE_SEAL);
		if (!ok) {
			DEBUG(0,("The gensec feature sealing request, but unavailable\n"));
			TALLOC_FREE(auth_generic_state);
			return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
		}

		ok = gensec_have_feature(auth_generic_state->gensec_security,
					 GENSEC_FEATURE_SIGN);
		if (!ok) {
			DEBUG(0,("The gensec feature signing request, but unavailable\n"));
			TALLOC_FREE(auth_generic_state);
			return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
		}

	} else if (wrap->wrap_type >= ADS_SASLWRAP_TYPE_SIGN) {
		bool ok;

		ok = gensec_have_feature(auth_generic_state->gensec_security,
					 GENSEC_FEATURE_SIGN);
		if (!ok) {
			DEBUG(0,("The gensec feature signing request, but unavailable\n"));
			TALLOC_FREE(auth_generic_state);
			return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
		}
	}

	ads->auth.tgs_expire = LONG_MAX;
	end_nt_time = gensec_expire_time(auth_generic_state->gensec_security);
	if (end_nt_time != GENSEC_EXPIRE_TIME_INFINITY) {
		struct timeval tv;
		nttime_to_timeval(&tv, end_nt_time);
		ads->auth.tgs_expire = tv.tv_sec;
	}

	if (wrap->wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
		size_t max_wrapped =
			gensec_max_wrapped_size(auth_generic_state->gensec_security);
		wrap->out.max_unwrapped =
			gensec_max_input_size(auth_generic_state->gensec_security);

		wrap->out.sig_size = max_wrapped - wrap->out.max_unwrapped;
		/*
		 * Note that we have to truncate this to 0x2C
		 * (taken from a capture with LDAP unbind), as the
		 * signature size is not constant for Kerberos with
		 * arcfour-hmac-md5.
		 */
		wrap->in.min_wrapped = MIN(wrap->out.sig_size, 0x2C);
		wrap->in.max_wrapped = ADS_SASL_WRAPPING_IN_MAX_WRAPPED;
		status = ads_setup_sasl_wrapping(wrap, ads->ldap.ld,
						 &ads_sasl_gensec_ops,
						 auth_generic_state->gensec_security);
		if (!ADS_ERR_OK(status)) {
			DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
				ads_errstr(status)));
			TALLOC_FREE(auth_generic_state);
			return status;
		}
		/* Only keep the gensec_security element around long-term */
		talloc_steal(NULL, auth_generic_state->gensec_security);
	}
	TALLOC_FREE(auth_generic_state);

	return ADS_ERROR(rc);
}
예제 #6
0
NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx,
			      const struct tsocket_address *remote_address,
			      struct gensec_security **gensec_security_out)
{
	struct gensec_security *gensec_security;
	struct auth_context *auth_context;
	NTSTATUS nt_status;

	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);

	nt_status = make_auth_context_subsystem(tmp_ctx, &auth_context);
	if (!NT_STATUS_IS_OK(nt_status)) {
		TALLOC_FREE(tmp_ctx);
		return nt_status;
	}

	if (auth_context->prepare_gensec) {
		nt_status = auth_context->prepare_gensec(auth_context, tmp_ctx,
							 &gensec_security);
		if (!NT_STATUS_IS_OK(nt_status)) {
			TALLOC_FREE(tmp_ctx);
			return nt_status;
		}
	} else {
		const struct gensec_security_ops **backends = NULL;
		struct gensec_settings *gensec_settings;
		struct loadparm_context *lp_ctx;
		size_t idx = 0;
		struct cli_credentials *server_credentials;
		const char *dns_name;
		const char *dns_domain;
		struct auth4_context *auth4_context = make_auth4_context_s3(tmp_ctx, auth_context);
		if (auth4_context == NULL) {
			TALLOC_FREE(tmp_ctx);
			return NT_STATUS_NO_MEMORY;
		}

		lp_ctx = loadparm_init_s3(tmp_ctx, loadparm_s3_helpers());
		if (lp_ctx == NULL) {
			DEBUG(10, ("loadparm_init_s3 failed\n"));
			TALLOC_FREE(tmp_ctx);
			return NT_STATUS_INVALID_SERVER_STATE;
		}

		gensec_settings = lpcfg_gensec_settings(tmp_ctx, lp_ctx);
		if (lp_ctx == NULL) {
			DEBUG(10, ("lpcfg_gensec_settings failed\n"));
			TALLOC_FREE(tmp_ctx);
			return NT_STATUS_NO_MEMORY;
		}

		/*
		 * This should be a 'netbios domain -> DNS domain'
		 * mapping, and can currently validly return NULL on
		 * poorly configured systems.
		 *
		 * This is used for the NTLMSSP server
		 *
		 */
		dns_name = get_mydnsfullname();
		if (dns_name == NULL) {
			dns_name = "";
		}

		dns_domain = get_mydnsdomname(tmp_ctx);
		if (dns_domain == NULL) {
			dns_domain = "";
		}

		gensec_settings->server_dns_name = strlower_talloc(gensec_settings, dns_name);
		if (gensec_settings->server_dns_name == NULL) {
			TALLOC_FREE(tmp_ctx);
			return NT_STATUS_NO_MEMORY;
		}

		gensec_settings->server_dns_domain = strlower_talloc(gensec_settings, dns_domain);
		if (gensec_settings->server_dns_domain == NULL) {
			TALLOC_FREE(tmp_ctx);
			return NT_STATUS_NO_MEMORY;
		}

		backends = talloc_zero_array(gensec_settings,
					     const struct gensec_security_ops *, 6);
		if (backends == NULL) {
			TALLOC_FREE(tmp_ctx);
			return NT_STATUS_NO_MEMORY;
		}
		gensec_settings->backends = backends;

		gensec_init();

		/* These need to be in priority order, krb5 before NTLMSSP */
#if defined(HAVE_KRB5)
		backends[idx++] = &gensec_gse_krb5_security_ops;
#endif

		backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_NTLMSSP);

		backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_SPNEGO);

		backends[idx++] = gensec_security_by_auth_type(NULL, DCERPC_AUTH_TYPE_SCHANNEL);

		backends[idx++] = gensec_security_by_auth_type(NULL, DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM);

		/*
		 * This is anonymous for now, because we just use it
		 * to set the kerberos state at the moment
		 */
		server_credentials = cli_credentials_init_anon(tmp_ctx);
		if (!server_credentials) {
			DEBUG(0, ("auth_generic_prepare: Failed to init server credentials\n"));
			return NT_STATUS_NO_MEMORY;
		}

		cli_credentials_set_conf(server_credentials, lp_ctx);

		if (lp_security() == SEC_ADS || USE_KERBEROS_KEYTAB) {
			cli_credentials_set_kerberos_state(server_credentials, CRED_AUTO_USE_KERBEROS);
		} else {
			cli_credentials_set_kerberos_state(server_credentials, CRED_DONT_USE_KERBEROS);
		}

		nt_status = gensec_server_start(tmp_ctx, gensec_settings,
						auth4_context, &gensec_security);

		if (!NT_STATUS_IS_OK(nt_status)) {
			TALLOC_FREE(tmp_ctx);
			return nt_status;
		}

		gensec_set_credentials(gensec_security, server_credentials);

		talloc_unlink(tmp_ctx, lp_ctx);
		talloc_unlink(tmp_ctx, server_credentials);
		talloc_unlink(tmp_ctx, gensec_settings);
		talloc_unlink(tmp_ctx, auth4_context);
	}

	nt_status = gensec_set_remote_address(gensec_security,
					      remote_address);
	if (!NT_STATUS_IS_OK(nt_status)) {
		TALLOC_FREE(tmp_ctx);
		return nt_status;
	}

	*gensec_security_out = talloc_steal(mem_ctx, gensec_security);
	TALLOC_FREE(tmp_ctx);
	return NT_STATUS_OK;
}
예제 #7
0
파일: session.c 프로젝트: rti7743/samba
/* Fill out the auth_session_info with a cli_credentials based on the
 * auth_session_info we were forwarded over named pipe forwarding.
 *
 * NOTE: The stucture members of session_info_transport are stolen
 * with talloc_move() into auth_session_info for long term use
 */
struct auth_session_info *auth_session_info_from_transport(TALLOC_CTX *mem_ctx,
        struct auth_session_info_transport *session_info_transport,
        struct loadparm_context *lp_ctx,
        const char **reason)
{
    struct auth_session_info *session_info;
    session_info = talloc_steal(mem_ctx, session_info_transport->session_info);

    if (session_info_transport->exported_gssapi_credentials.length) {
        struct cli_credentials *creds;
        OM_uint32 minor_status;
        gss_buffer_desc cred_token;
        gss_cred_id_t cred_handle;
        const char *error_string;
        int ret;

        DEBUG(10, ("Delegated credentials supplied by client\n"));

        cred_token.value = session_info_transport->exported_gssapi_credentials.data;
        cred_token.length = session_info_transport->exported_gssapi_credentials.length;

        ret = gss_import_cred(&minor_status,
                              &cred_token,
                              &cred_handle);
        if (ret != GSS_S_COMPLETE) {
            *reason = "Internal error in gss_import_cred()";
            return NULL;
        }

        creds = cli_credentials_init(session_info);
        if (!creds) {
            *reason = "Out of memory in cli_credentials_init()";
            return NULL;
        }
        session_info->credentials = creds;

        cli_credentials_set_conf(creds, lp_ctx);
        /* Just so we don't segfault trying to get at a username */
        cli_credentials_set_anonymous(creds);

        ret = cli_credentials_set_client_gss_creds(creds,
                lp_ctx,
                cred_handle,
                CRED_SPECIFIED,
                &error_string);
        if (ret) {
            *reason = talloc_asprintf(mem_ctx,
                                      "Failed to set pipe forwarded"
                                      "creds: %s\n", error_string);
            return NULL;
        }

        /* This credential handle isn't useful for password
         * authentication, so ensure nobody tries to do that */
        cli_credentials_set_kerberos_state(creds,
                                           CRED_MUST_USE_KERBEROS);

    }

    return session_info;
}
예제 #8
0
파일: sasl.c 프로젝트: DanilKorotenko/samba
/* 
   perform a LDAP/SASL/SPNEGO/{NTLMSSP,KRB5} bind (just how many layers can
   we fit on one socket??)
*/
static ADS_STATUS ads_sasl_spnego_gensec_bind(ADS_STRUCT *ads,
				const char *sasl,
				enum credentials_use_kerberos krb5_state,
				const char *target_service,
				const char *target_hostname,
				const DATA_BLOB server_blob)
{
	DATA_BLOB blob_in = data_blob_null;
	DATA_BLOB blob_out = data_blob_null;
	int rc;
	NTSTATUS nt_status;
	ADS_STATUS status;
	struct auth_generic_state *auth_generic_state;
	bool use_spnego_principal = lp_client_use_spnego_principal();
	const char *sasl_list[] = { sasl, NULL };

	nt_status = auth_generic_client_prepare(NULL, &auth_generic_state);
	if (!NT_STATUS_IS_OK(nt_status)) {
		return ADS_ERROR_NT(nt_status);
	}

	if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_username(auth_generic_state, ads->auth.user_name))) {
		return ADS_ERROR_NT(nt_status);
	}
	if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_domain(auth_generic_state, ads->auth.realm))) {
		return ADS_ERROR_NT(nt_status);
	}
	if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_password(auth_generic_state, ads->auth.password))) {
		return ADS_ERROR_NT(nt_status);
	}

	if (server_blob.length == 0) {
		use_spnego_principal = false;
	}

	if (krb5_state == CRED_DONT_USE_KERBEROS) {
		use_spnego_principal = false;
	}

	cli_credentials_set_kerberos_state(auth_generic_state->credentials,
					   krb5_state);

	if (target_service != NULL) {
		nt_status = gensec_set_target_service(
					auth_generic_state->gensec_security,
					target_service);
		if (!NT_STATUS_IS_OK(nt_status)) {
			return ADS_ERROR_NT(nt_status);
		}
	}

	if (target_hostname != NULL) {
		nt_status = gensec_set_target_hostname(
					auth_generic_state->gensec_security,
					target_hostname);
		if (!NT_STATUS_IS_OK(nt_status)) {
			return ADS_ERROR_NT(nt_status);
		}
	}

	if (target_service != NULL && target_hostname != NULL) {
		use_spnego_principal = false;
	}

	switch (ads->ldap.wrap_type) {
	case ADS_SASLWRAP_TYPE_SEAL:
		gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
		gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SEAL);
		break;
	case ADS_SASLWRAP_TYPE_SIGN:
		if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
			gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
		} else {
			/*
			 * windows servers are broken with sign only,
			 * so we let the NTLMSSP backend to seal here,
			 * via GENSEC_FEATURE_LDAP_STYLE.
			 */
			gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
			gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_LDAP_STYLE);
		}
		break;
	case ADS_SASLWRAP_TYPE_PLAIN:
		break;
	}

	nt_status = auth_generic_client_start_by_sasl(auth_generic_state,
						      sasl_list);
	if (!NT_STATUS_IS_OK(nt_status)) {
		return ADS_ERROR_NT(nt_status);
	}

	rc = LDAP_SASL_BIND_IN_PROGRESS;
	nt_status = NT_STATUS_MORE_PROCESSING_REQUIRED;
	if (use_spnego_principal) {
		blob_in = data_blob_dup_talloc(talloc_tos(), server_blob);
		if (blob_in.length == 0) {
			TALLOC_FREE(auth_generic_state);
			return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
		}
	} else {
		blob_in = data_blob_null;
	}
	blob_out = data_blob_null;

	while (true) {
		struct berval cred, *scred = NULL;

		nt_status = gensec_update(auth_generic_state->gensec_security,
					  talloc_tos(), blob_in, &blob_out);
		data_blob_free(&blob_in);
		if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)
		    && !NT_STATUS_IS_OK(nt_status))
		{
			TALLOC_FREE(auth_generic_state);
			data_blob_free(&blob_out);
			return ADS_ERROR_NT(nt_status);
		}

		if (NT_STATUS_IS_OK(nt_status) && rc == 0 && blob_out.length == 0) {
			break;
		}

		cred.bv_val = (char *)blob_out.data;
		cred.bv_len = blob_out.length;
		scred = NULL;
		rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, sasl, &cred, NULL, NULL, &scred);
		data_blob_free(&blob_out);
		if ((rc != LDAP_SASL_BIND_IN_PROGRESS) && (rc != 0)) {
			if (scred) {
				ber_bvfree(scred);
			}

			TALLOC_FREE(auth_generic_state);
			return ADS_ERROR(rc);
		}
		if (scred) {
			blob_in = data_blob_talloc(talloc_tos(),
						   scred->bv_val,
						   scred->bv_len);
			if (blob_in.length != scred->bv_len) {
				ber_bvfree(scred);
				TALLOC_FREE(auth_generic_state);
				return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
			}
			ber_bvfree(scred);
		} else {
			blob_in = data_blob_null;
		}
		if (NT_STATUS_IS_OK(nt_status) && rc == 0 && blob_in.length == 0) {
			break;
		}
	}

	data_blob_free(&blob_in);
	data_blob_free(&blob_out);

	if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
		size_t max_wrapped = gensec_max_wrapped_size(auth_generic_state->gensec_security);
		ads->ldap.out.max_unwrapped = gensec_max_input_size(auth_generic_state->gensec_security);

		ads->ldap.out.sig_size = max_wrapped - ads->ldap.out.max_unwrapped;
		ads->ldap.in.min_wrapped = ads->ldap.out.sig_size;
		ads->ldap.in.max_wrapped = max_wrapped;
		status = ads_setup_sasl_wrapping(ads, &ads_sasl_gensec_ops, auth_generic_state->gensec_security);
		if (!ADS_ERR_OK(status)) {
			DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
				ads_errstr(status)));
			TALLOC_FREE(auth_generic_state);
			return status;
		}
		/* Only keep the gensec_security element around long-term */
		talloc_steal(NULL, auth_generic_state->gensec_security);
	}
	TALLOC_FREE(auth_generic_state);

	return ADS_ERROR(rc);
}
예제 #9
0
static void popt_common_credentials_callback(poptContext con, 
						enum poptCallbackReason reason,
						const struct poptOption *opt,
						const char *arg, const void *data)
{
	if (reason == POPT_CALLBACK_REASON_PRE) {
		cmdline_credentials = cli_credentials_init(talloc_autofree_context());
		return;
	}
	
	if (reason == POPT_CALLBACK_REASON_POST) {
		cli_credentials_guess(cmdline_credentials, cmdline_lp_ctx);

		if (!dont_ask) {
			cli_credentials_set_cmdline_callbacks(cmdline_credentials);
		}
		return;
	}

	switch(opt->val) {
	case 'U':
	{
		char *lp;
		
		cli_credentials_parse_string(cmdline_credentials, arg, CRED_SPECIFIED);
		/* This breaks the abstraction, including the const above */
		if ((lp=strchr_m(arg,'%'))) {
			lp[0]='\0';
			lp++;
			/* Try to prevent this showing up in ps */
			memset(lp,0,strlen(lp));
		}
	}
	break;

	case OPT_PASSWORD:
		cli_credentials_set_password(cmdline_credentials, arg, CRED_SPECIFIED);
		/* Try to prevent this showing up in ps */
		memset(discard_const(arg),0,strlen(arg));
		break;

	case 'A':
		cli_credentials_parse_file(cmdline_credentials, arg, CRED_SPECIFIED);
		break;

	case 'P':
		/* Later, after this is all over, get the machine account details from the secrets.ldb */
		cli_credentials_set_machine_account_pending(cmdline_credentials, cmdline_lp_ctx);
		break;

	case OPT_KERBEROS:
	{
		bool use_kerberos = true;
		/* Force us to only use kerberos */
		if (arg) {
			if (!set_boolean(arg, &use_kerberos)) {
				fprintf(stderr, "Error parsing -k %s\n", arg);
				exit(1);
				break;
			}
		}
		
		cli_credentials_set_kerberos_state(cmdline_credentials, 
						   use_kerberos 
						   ? CRED_MUST_USE_KERBEROS
						   : CRED_DONT_USE_KERBEROS);
		break;
	}
		
	case OPT_SIMPLE_BIND_DN:
		cli_credentials_set_bind_dn(cmdline_credentials, arg);
		break;
	}
}
예제 #10
0
static int set_ldap_credentials(struct ldb_context *ldb, bool use_external)
{
	const char *secrets_ldb_path, *sam_ldb_path;
	char *private_dir, *p, *error_string;
	struct ldb_context *secrets_ldb;
	struct cli_credentials *cred;
	struct loadparm_context *lp_ctx = ldb_get_opaque(ldb, "loadparm");
	TALLOC_CTX *tmp_ctx = talloc_new(ldb);

	if (!tmp_ctx) {
		return ldb_oom(ldb);
	}

	cred = cli_credentials_init(ldb);
	if (!cred) {
		talloc_free(tmp_ctx);
		return ldb_oom(ldb);
	}
	cli_credentials_set_anonymous(cred);
	if (use_external) {
		cli_credentials_set_forced_sasl_mech(cred, "EXTERNAL");
	} else {
		cli_credentials_set_forced_sasl_mech(cred, "DIGEST-MD5");

		/*
		 * We don't want to use krb5 to talk to our samdb - recursion
		 * here would be bad, and this account isn't in the KDC
		 * anyway
		 */
		cli_credentials_set_kerberos_state(cred, CRED_DONT_USE_KERBEROS);

		/*
		 * Work out where *our* secrets.ldb is.  It must be in
		 * the same directory as sam.ldb
		 */
		sam_ldb_path = (const char *)ldb_get_opaque(ldb, "ldb_url");
		if (!sam_ldb_path) {
			talloc_free(tmp_ctx);
			return ldb_operr(ldb);
		}
		if (strncmp("tdb://", sam_ldb_path, 6) == 0) {
			sam_ldb_path += 6;
		}
		private_dir = talloc_strdup(tmp_ctx, sam_ldb_path);
		p = strrchr(private_dir, '/');
		if (p) {
			*p = '\0';
		} else {
			private_dir = talloc_strdup(tmp_ctx, ".");
		}

		secrets_ldb_path = talloc_asprintf(private_dir, "tdb://%s/secrets.ldb",
						   private_dir);

		if (!secrets_ldb_path) {
			talloc_free(tmp_ctx);
			return ldb_oom(ldb);
		}

		/*
		 * Now that we have found the location, connect to
		 * secrets.ldb so we can read the SamDB Credentials
		 * record
		 */
		secrets_ldb = ldb_wrap_connect(tmp_ctx, NULL, lp_ctx, secrets_ldb_path,
					       NULL, NULL, 0);

		if (!NT_STATUS_IS_OK(cli_credentials_set_secrets(cred, NULL, secrets_ldb, NULL,
								 SECRETS_LDAP_FILTER, &error_string))) {
			ldb_asprintf_errstring(ldb, "Failed to read LDAP backend password from %s", secrets_ldb_path);
			talloc_free(tmp_ctx);
			return LDB_ERR_STRONG_AUTH_REQUIRED;
		}
	}

	/*
	 * Finally overwrite any supplied credentials with
	 * these ones, as only secrets.ldb contains the magic
	 * credentials to talk on the ldapi socket
	 */
	if (ldb_set_opaque(ldb, "credentials", cred)) {
		talloc_free(tmp_ctx);
		return ldb_operr(ldb);
	}
	talloc_free(tmp_ctx);
	return LDB_SUCCESS;
}
예제 #11
0
/* Get some basic (and authorization) information about the user on
 * this session.  This uses either the PAC (if present) or a local
 * database lookup */
static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_security,
					   TALLOC_CTX *mem_ctx,
					   struct auth_session_info **_session_info) 
{
	NTSTATUS nt_status;
	TALLOC_CTX *tmp_ctx;
	struct gensec_gssapi_state *gensec_gssapi_state
		= talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
	struct auth_session_info *session_info = NULL;
	OM_uint32 maj_stat, min_stat;
	DATA_BLOB pac_blob, *pac_blob_ptr = NULL;

	gss_buffer_desc name_token;
	char *principal_string;
	
	tmp_ctx = talloc_named(mem_ctx, 0, "gensec_gssapi_session_info context");
	NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);

	maj_stat = gss_display_name (&min_stat,
				     gensec_gssapi_state->client_name,
				     &name_token,
				     NULL);
	if (GSS_ERROR(maj_stat)) {
		DEBUG(1, ("GSS display_name failed: %s\n",
			  gssapi_error_string(tmp_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
		talloc_free(tmp_ctx);
		return NT_STATUS_FOOBAR;
	}

	principal_string = talloc_strndup(tmp_ctx,
					  (const char *)name_token.value,
					  name_token.length);

	gss_release_buffer(&min_stat, &name_token);

	if (!principal_string) {
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	nt_status = gssapi_obtain_pac_blob(tmp_ctx,  gensec_gssapi_state->gssapi_context,
					   gensec_gssapi_state->client_name,
					   &pac_blob);
	
	/* IF we have the PAC - otherwise we need to get this
	 * data from elsewere - local ldb, or (TODO) lookup of some
	 * kind... 
	 */
	if (NT_STATUS_IS_OK(nt_status)) {
		pac_blob_ptr = &pac_blob;
	}
	nt_status = gensec_generate_session_info_pac(tmp_ctx,
						     gensec_security,
						     gensec_gssapi_state->smb_krb5_context,
						     pac_blob_ptr, principal_string,
						     gensec_get_remote_address(gensec_security),
						     &session_info);
	if (!NT_STATUS_IS_OK(nt_status)) {
		talloc_free(tmp_ctx);
		return nt_status;
	}

	nt_status = gensec_gssapi_session_key(gensec_security, session_info, &session_info->session_key);
	if (!NT_STATUS_IS_OK(nt_status)) {
		talloc_free(tmp_ctx);
		return nt_status;
	}

	if (gensec_gssapi_state->gss_got_flags & GSS_C_DELEG_FLAG &&
	    gensec_gssapi_state->delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
		krb5_error_code ret;
		const char *error_string;

		DEBUG(10, ("gensec_gssapi: delegated credentials supplied by client\n"));
		session_info->credentials = cli_credentials_init(session_info);
		if (!session_info->credentials) {
			talloc_free(tmp_ctx);
			return NT_STATUS_NO_MEMORY;
		}

		cli_credentials_set_conf(session_info->credentials, gensec_security->settings->lp_ctx);
		/* Just so we don't segfault trying to get at a username */
		cli_credentials_set_anonymous(session_info->credentials);
		
		ret = cli_credentials_set_client_gss_creds(session_info->credentials, 
							   gensec_security->settings->lp_ctx,
							   gensec_gssapi_state->delegated_cred_handle,
							   CRED_SPECIFIED, &error_string);
		if (ret) {
			talloc_free(tmp_ctx);
			DEBUG(2,("Failed to get gss creds: %s\n", error_string));
			return NT_STATUS_NO_MEMORY;
		}
		
		/* This credential handle isn't useful for password authentication, so ensure nobody tries to do that */
		cli_credentials_set_kerberos_state(session_info->credentials, CRED_MUST_USE_KERBEROS);

		/* It has been taken from this place... */
		gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL;
	} else {
		DEBUG(10, ("gensec_gssapi: NO delegated credentials supplied by client\n"));
	}

	*_session_info = talloc_steal(mem_ctx, session_info);
	talloc_free(tmp_ctx);

	return NT_STATUS_OK;
}
예제 #12
0
파일: credentials.c 프로젝트: GSam/samba
/**
 * Create a new credentials structure
 * @param mem_ctx TALLOC_CTX parent for credentials structure 
 */
_PUBLIC_ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx) 
{
	struct cli_credentials *cred = talloc(mem_ctx, struct cli_credentials);
	if (cred == NULL) {
		return cred;
	}

	cred->workstation_obtained = CRED_UNINITIALISED;
	cred->username_obtained = CRED_UNINITIALISED;
	cred->password_obtained = CRED_UNINITIALISED;
	cred->domain_obtained = CRED_UNINITIALISED;
	cred->realm_obtained = CRED_UNINITIALISED;
	cred->ccache_obtained = CRED_UNINITIALISED;
	cred->client_gss_creds_obtained = CRED_UNINITIALISED;
	cred->principal_obtained = CRED_UNINITIALISED;
	cred->keytab_obtained = CRED_UNINITIALISED;
	cred->server_gss_creds_obtained = CRED_UNINITIALISED;

	cred->ccache_threshold = CRED_UNINITIALISED;
	cred->client_gss_creds_threshold = CRED_UNINITIALISED;

	cred->workstation = NULL;
	cred->username = NULL;
	cred->password = NULL;
	cred->old_password = NULL;
	cred->domain = NULL;
	cred->realm = NULL;
	cred->principal = NULL;
	cred->salt_principal = NULL;
	cred->impersonate_principal = NULL;
	cred->self_service = NULL;
	cred->target_service = NULL;

	cred->bind_dn = NULL;

	cred->nt_hash = NULL;
	cred->old_nt_hash = NULL;

	cred->lm_response.data = NULL;
	cred->lm_response.length = 0;
	cred->nt_response.data = NULL;
	cred->nt_response.length = 0;

	cred->ccache = NULL;
	cred->client_gss_creds = NULL;
	cred->keytab = NULL;
	cred->server_gss_creds = NULL;

	cred->workstation_cb = NULL;
	cred->password_cb = NULL;
	cred->username_cb = NULL;
	cred->domain_cb = NULL;
	cred->realm_cb = NULL;
	cred->principal_cb = NULL;

	cred->priv_data = NULL;

	cred->netlogon_creds = NULL;
	cred->secure_channel_type = SEC_CHAN_NULL;

	cred->kvno = 0;

	cred->password_last_changed_time = 0;

	cred->smb_krb5_context = NULL;

	cred->machine_account_pending = false;
	cred->machine_account_pending_lp_ctx = NULL;

	cred->machine_account = false;

	cred->password_tries = 0;

	cred->callback_running = false;

	cli_credentials_set_kerberos_state(cred, CRED_AUTO_USE_KERBEROS);
	cli_credentials_set_gensec_features(cred, 0);
	cli_credentials_set_krb_forwardable(cred, CRED_AUTO_KRB_FORWARDABLE);

	cred->forced_sasl_mech = NULL;

	return cred;
}
예제 #13
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;
	int server_role = lpcfg_server_role(lp_ctx);
	int security = lpcfg_security(lp_ctx);
	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) {
		enum credentials_use_kerberos use_kerberos = CRED_DONT_USE_KERBEROS;
		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);

			switch (server_role) {
			case ROLE_DOMAIN_MEMBER:
				if (security != SEC_ADS) {
					break;
				}

				FALL_THROUGH;
			case ROLE_ACTIVE_DIRECTORY_DC:
				use_kerberos = CRED_AUTO_USE_KERBEROS;
				break;
			}
		}
		cli_credentials_set_kerberos_state(cred, use_kerberos);
		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;
}