/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 | lws_ss_destroy(&m->ss); |
81 | |
|
82 | 0 | if (lws_ss_policy_set(context, "updated")) |
83 | 0 | lwsl_err("%s: policy set failed\n", __func__); |
84 | 0 | else { |
85 | 0 | context->policy_updated = 1; |
86 | 0 | #if defined(LWS_WITH_SYS_STATE) |
87 | 0 | lws_state_transition_steps(&context->mgr_system, |
88 | 0 | LWS_SYSTATE_OPERATIONAL); |
89 | 0 | #endif |
90 | 0 | } |
91 | 0 | } |
92 | | |
93 | | static lws_ss_state_return_t |
94 | | ss_fetch_policy_state(void *userobj, void *sh, lws_ss_constate_t state, |
95 | | lws_ss_tx_ordinal_t ack) |
96 | 0 | { |
97 | 0 | ss_fetch_policy_t *m = (ss_fetch_policy_t *)userobj; |
98 | 0 | struct lws_context *context = (struct lws_context *)m->opaque_data; |
99 | |
|
100 | 0 | lwsl_info("%s: %s, ord 0x%x\n", __func__, lws_ss_state_name(state), |
101 | 0 | (unsigned int)ack); |
102 | |
|
103 | 0 | switch (state) { |
104 | 0 | case LWSSSCS_CREATING: |
105 | 0 | return lws_ss_request_tx(m->ss); |
106 | | |
107 | 0 | case LWSSSCS_CONNECTING: |
108 | 0 | break; |
109 | | |
110 | 0 | case LWSSSCS_QOS_ACK_REMOTE: |
111 | 0 | switch (m->partway) { |
112 | 0 | case 2: |
113 | 0 | lws_sul_schedule(context, 0, &m->sul, policy_set, 1); |
114 | 0 | m->partway = 0; |
115 | 0 | break; |
116 | 0 | } |
117 | 0 | break; |
118 | | |
119 | 0 | case LWSSSCS_DISCONNECTED: |
120 | 0 | if (m->partway == 1) { |
121 | 0 | lws_ss_policy_parse_abandon(context); |
122 | 0 | break; |
123 | 0 | } |
124 | 0 | m->partway = 0; |
125 | 0 | break; |
126 | | |
127 | 0 | default: |
128 | 0 | break; |
129 | 0 | } |
130 | | |
131 | 0 | return LWSSSSRET_OK; |
132 | 0 | } |
133 | | |
134 | | int |
135 | | lws_ss_sys_fetch_policy(struct lws_context *context) |
136 | 0 | { |
137 | 0 | lws_ss_info_t ssi; |
138 | |
|
139 | 0 | if (context->hss_fetch_policy) /* already exists */ |
140 | 0 | return 0; |
141 | | |
142 | | /* We're making an outgoing secure stream ourselves */ |
143 | | |
144 | 0 | memset(&ssi, 0, sizeof(ssi)); |
145 | 0 | ssi.handle_offset = offsetof(ss_fetch_policy_t, ss); |
146 | 0 | ssi.opaque_user_data_offset = offsetof(ss_fetch_policy_t, opaque_data); |
147 | 0 | ssi.rx = ss_fetch_policy_rx; |
148 | 0 | ssi.tx = ss_fetch_policy_tx; |
149 | 0 | ssi.state = ss_fetch_policy_state; |
150 | 0 | ssi.user_alloc = sizeof(ss_fetch_policy_t); |
151 | 0 | ssi.streamtype = "fetch_policy"; |
152 | |
|
153 | 0 | if (lws_ss_create(context, 0, &ssi, context, &context->hss_fetch_policy, |
154 | 0 | NULL, NULL)) { |
155 | | /* |
156 | | * If there's no fetch_policy streamtype, it can just be we're |
157 | | * running on a proxied client with no policy of its own, |
158 | | * it's OK. |
159 | | */ |
160 | 0 | lwsl_info("%s: Policy fetch ss failed (stub policy?)\n", __func__); |
161 | |
|
162 | 0 | return 0; |
163 | 0 | } |
164 | | |
165 | 0 | lwsl_info("%s: policy fetching ongoing\n", __func__); |
166 | | |
167 | | /* fetching it is ongoing */ |
168 | |
|
169 | 0 | return 1; |
170 | 0 | } |