basic/
basic.rs

1//! This example uses the asynchronous proxy instances.
2//!
3//! The client configuration must be passed as a string blob, including any certificates/keys inline (PEM format). A basic username/password authentication handler is also included.
4//!
5
6use async_std::task;
7
8static CONFIG_STR: &str = "
9client
10dev tun
11persist-tun
12persist-key
13proto udp
14remote my-server 1194
15resolv-retry infinite
16<ca>
17-----BEGIN CERTIFICATE-----
18-----END CERTIFICATE-----
19</ca>
20<cert>
21-----BEGIN CERTIFICATE-----
22-----END CERTIFICATE-----
23</cert>
24<key>
25-----BEGIN PRIVATE KEY-----
26-----END PRIVATE KEY-----
27</key>
28<tls-auth>
29-----BEGIN OpenVPN Static key V1-----
30-----END OpenVPN Static key V1-----
31</tls-auth>
32key-direction 1
33remote-cert-tls server
34auth-user-pass
35pull
36";
37
38fn main() {
39    task::block_on(async {
40        let connection = zbus::Connection::system().await.unwrap();
41        let config_manager = openvpn3_rs::ConfigurationProxy::new(&connection)
42            .await
43            .unwrap();
44        let config = config_manager
45            .import("My VPN", CONFIG_STR, true, false)
46            .await
47            .unwrap();
48
49        let sessions_manager = openvpn3_rs::SessionsProxy::new(&connection).await.unwrap();
50        let session = sessions_manager.new_tunnel(&config.path()).await.unwrap();
51
52        let mut ready = false;
53        while !ready {
54            // If the session is ready, the `ready()` method will return Ok(), otherwise an error will be returned with more details.
55            if let Err(err) = session.ready().await {
56                let err_str = err.to_string();
57                if err_str.contains("Missing user credentials") {
58                    // This loop queries the session for which credentials are needed. This example covers username/password authentication.
59
60                    let ui_type_group = session.user_input_queue_get_type_group().await.unwrap();
61
62                    for (ca_type, ca_group) in ui_type_group {
63                        let ui_queue_ids = session
64                            .user_input_queue_check(ca_type, ca_group)
65                            .await
66                            .unwrap();
67
68                        for id in ui_queue_ids {
69                            let (ca_type, ca_group, id, name, _description, _hidden_input) =
70                                session
71                                    .user_input_queue_fetch(ca_type, ca_group, id)
72                                    .await
73                                    .unwrap();
74
75                            if name == "username" {
76                                session
77                                    .user_input_provide(ca_type, ca_group, id, "smith")
78                                    .await
79                                    .unwrap();
80                            }
81
82                            if name == "password" {
83                                session
84                                    .user_input_provide(ca_type, ca_group, id, "hunter2")
85                                    .await
86                                    .unwrap();
87                            }
88                        }
89                    }
90                } else if err_str.contains("Backend VPN process is not ready") {
91                    task::sleep(std::time::Duration::from_secs(1)).await;
92                }
93            } else {
94                ready = true;
95            }
96        }
97
98        session.connect().await.unwrap();
99
100        // wait for signal to disconnect
101
102        session.disconnect().await.unwrap();
103    });
104}