/src/libwebsockets/lib/secure-streams/system/fetch-policy/fetch-policy.c
Line | Count | Source |
1 | | /* |
2 | | * Policy fetching for Secure Streams |
3 | | * |
4 | | * libwebsockets - small server side websockets and web server implementation |
5 | | * |
6 | | * Copyright (C) 2019 - 2020 Andy Green <andy@warmcat.com> |
7 | | * |
8 | | * Permission is hereby granted, free of charge, to any person obtaining a copy |
9 | | * of this software and associated documentation files (the "Software"), to |
10 | | * deal in the Software without restriction, including without limitation the |
11 | | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
12 | | * sell copies of the Software, and to permit persons to whom the Software is |
13 | | * furnished to do so, subject to the following conditions: |
14 | | * |
15 | | * The above copyright notice and this permission notice shall be included in |
16 | | * all copies or substantial portions of the Software. |
17 | | * |
18 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
19 | | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
20 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
21 | | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
22 | | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
23 | | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
24 | | * IN THE SOFTWARE. |
25 | | */ |
26 | | |
27 | | #include <private-lib-core.h> |
28 | | |
29 | | typedef struct ss_fetch_policy { |
30 | | struct lws_ss_handle *ss; |
31 | | void *opaque_data; |
32 | | /* ... application specific state ... */ |
33 | | |
34 | | lws_sorted_usec_list_t sul; |
35 | | |
36 | | uint8_t partway; |
37 | | } ss_fetch_policy_t; |
38 | | |
39 | | /* secure streams payload interface */ |
40 | | |
41 | | static lws_ss_state_return_t |
42 | | ss_fetch_policy_rx(void *userobj, const uint8_t *buf, size_t len, int flags) |
43 | 0 | { |
44 | 0 | ss_fetch_policy_t *m = (ss_fetch_policy_t *)userobj; |
45 | 0 | struct lws_context *context = (struct lws_context *)m->opaque_data; |
46 | |
|
47 | 0 | if (flags & LWSSS_FLAG_SOM) { |
48 | 0 | if (lws_ss_policy_parse_begin(context, 0)) |
49 | 0 | return LWSSSSRET_OK; |
50 | 0 | m->partway = 1; |
51 | 0 | } |
52 | | |
53 | 0 | if (len && lws_ss_policy_parse(context, buf, len) < 0) |
54 | 0 | return LWSSSSRET_OK; |
55 | | |
56 | 0 | if (flags & LWSSS_FLAG_EOM) |
57 | 0 | m->partway = 2; |
58 | |
|
59 | 0 | return LWSSSSRET_OK; |
60 | 0 | } |
61 | | |
62 | | static lws_ss_state_return_t |
63 | | ss_fetch_policy_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, |
64 | | size_t *len, int *flags) |
65 | 0 | { |
66 | 0 | return LWSSSSRET_TX_DONT_SEND; |
67 | 0 | } |
68 | | |
69 | | static void |
70 | | policy_set(lws_sorted_usec_list_t *sul) |
71 | 0 | { |
72 | 0 | ss_fetch_policy_t *m = lws_container_of(sul, ss_fetch_policy_t, sul); |
73 | 0 | struct lws_context *context = (struct lws_context *)m->opaque_data; |
74 | | |
75 | | /* |
76 | | * We get called if the policy parse was successful, just after the |
77 | | * ss connection close that was using the vhost from the old policy |
78 | | */ |
79 | |
|
80 | 0 | context->hss_fetch_policy = NULL; |
81 | 0 | lws_ss_destroy(&m->ss); |
82 | |
|
83 | 0 | if (lws_ss_policy_set(context, "updated")) |
84 | 0 | lwsl_err("%s: policy set failed\n", __func__); |
85 | 0 | else { |
86 | 0 | context->policy_updated = 1; |
87 | 0 | #if defined(LWS_WITH_SYS_STATE) |
88 | 0 | lws_state_transition_steps(&context->mgr_system, |
89 | 0 | LWS_SYSTATE_OPERATIONAL); |
90 | 0 | #endif |
91 | 0 | } |
92 | 0 | } |
93 | | |
94 | | static lws_ss_state_return_t |
95 | | ss_fetch_policy_state(void *userobj, void *sh, lws_ss_constate_t state, |
96 | | lws_ss_tx_ordinal_t ack) |
97 | 0 | { |
98 | 0 | ss_fetch_policy_t *m = (ss_fetch_policy_t *)userobj; |
99 | 0 | struct lws_context *context = (struct lws_context *)m->opaque_data; |
100 | |
|
101 | 0 | lwsl_info("%s: %s, ord 0x%x\n", __func__, lws_ss_state_name(state), |
102 | 0 | (unsigned int)ack); |
103 | |
|
104 | 0 | switch (state) { |
105 | 0 | case LWSSSCS_CREATING: |
106 | 0 | return lws_ss_request_tx(m->ss); |
107 | | |
108 | 0 | case LWSSSCS_CONNECTING: |
109 | 0 | break; |
110 | | |
111 | 0 | case LWSSSCS_QOS_ACK_REMOTE: |
112 | 0 | switch (m->partway) { |
113 | 0 | case 2: |
114 | 0 | lws_sul_schedule(context, 0, &m->sul, policy_set, 1); |
115 | 0 | m->partway = 0; |
116 | 0 | break; |
117 | 0 | } |
118 | 0 | break; |
119 | | |
120 | 0 | case LWSSSCS_DISCONNECTED: |
121 | 0 | if (m->partway == 1) { |
122 | 0 | lws_ss_policy_parse_abandon(context); |
123 | 0 | break; |
124 | 0 | } |
125 | 0 | m->partway = 0; |
126 | 0 | break; |
127 | | |
128 | 0 | default: |
129 | 0 | break; |
130 | 0 | } |
131 | | |
132 | 0 | return LWSSSSRET_OK; |
133 | 0 | } |
134 | | |
135 | | int |
136 | | lws_ss_sys_fetch_policy(struct lws_context *context) |
137 | 0 | { |
138 | 0 | lws_ss_info_t ssi; |
139 | |
|
140 | 0 | if (context->hss_fetch_policy) /* already exists */ |
141 | 0 | return 0; |
142 | | |
143 | | /* We're making an outgoing secure stream ourselves */ |
144 | | |
145 | 0 | memset(&ssi, 0, sizeof(ssi)); |
146 | 0 | ssi.handle_offset = offsetof(ss_fetch_policy_t, ss); |
147 | 0 | ssi.opaque_user_data_offset = offsetof(ss_fetch_policy_t, opaque_data); |
148 | 0 | ssi.rx = ss_fetch_policy_rx; |
149 | 0 | ssi.tx = ss_fetch_policy_tx; |
150 | 0 | ssi.state = ss_fetch_policy_state; |
151 | 0 | ssi.user_alloc = sizeof(ss_fetch_policy_t); |
152 | 0 | ssi.streamtype = "fetch_policy"; |
153 | |
|
154 | 0 | if (lws_ss_create(context, 0, &ssi, context, &context->hss_fetch_policy, |
155 | 0 | NULL, NULL)) { |
156 | | /* |
157 | | * If there's no fetch_policy streamtype, it can just be we're |
158 | | * running on a proxied client with no policy of its own, |
159 | | * it's OK. |
160 | | */ |
161 | 0 | lwsl_info("%s: Policy fetch ss failed (stub policy?)\n", __func__); |
162 | |
|
163 | 0 | return 0; |
164 | 0 | } |
165 | | |
166 | 0 | lwsl_info("%s: policy fetching ongoing\n", __func__); |
167 | | |
168 | | /* fetching it is ongoing */ |
169 | |
|
170 | 0 | return 1; |
171 | 0 | } |