1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

ss: policy: add auth mapping section

This commit is contained in:
Andy Green 2020-08-19 11:21:58 +01:00
parent ce3b99cd8f
commit 940abe557a
9 changed files with 210 additions and 23 deletions

View file

@ -178,6 +178,20 @@ typedef struct lws_ss_http_respmap {
uint16_t state; /* low 16-bits of associated state */
} lws_ss_http_respmap_t;
/*
* This is a mapping between an auth streamtype and a name and other information
* that can be independently instantiated. Other streamtypes can indicate they
* require this authentication on their connection.
*/
typedef struct lws_ss_auth {
struct lws_ss_auth *next;
const char *name;
const char *streamtype;
uint8_t blob_index;
} lws_ss_auth_t;
/**
* lws_ss_policy_t: policy database entry for a stream type
*
@ -202,6 +216,7 @@ typedef struct lws_ss_policy {
const char *payload_fmt;
const char *socks5_proxy;
lws_ss_metadata_t *metadata; /* linked-list of metadata */
const lws_ss_auth_t *auth; /* NULL or auth object we bind to */
/* protocol-specific connection policy details */
@ -326,10 +341,14 @@ LWS_VISIBLE LWS_EXTERN int
lws_ss_policy_overlay(struct lws_context *context, const char *overlay);
/*
* You almost certainly don't want this, it returns the first policy object
* in a linked-list of objects created by lws_ss_policy_parse above
* You almost certainly don't want these, they return the first policy or auth
* object in a linked-list of objects created by lws_ss_policy_parse above,
* they are exported to generate static policy with
*/
LWS_VISIBLE LWS_EXTERN const lws_ss_policy_t *
lws_ss_policy_get(struct lws_context *context);
LWS_VISIBLE LWS_EXTERN const lws_ss_auth_t *
lws_ss_auth_get(struct lws_context *context);
#endif

View file

@ -554,6 +554,7 @@ struct lws_context {
void *pol_args;
#endif
const lws_ss_policy_t *pss_policies;
const lws_ss_auth_t *pss_auths;
#if defined(LWS_WITH_SSPLUGINS)
const lws_ss_plugin_t **pss_plugins;
#endif

View file

@ -210,6 +210,34 @@ with one of these to enforce validity checking of the remote server.
Entries should be named using "name" and the stack array defined using "stack"
### `auth`
Optional section describing a map of available authentication streamtypes to
auth token blob indexes.
```
...
"auth": [{"name":"lwa","streamtype":"api_amazon_com_lwa","blob":0}]
...
```
Streams can indicate they depend on a valid auth token from one of these schemes
by using the `"use_auth": "name"` member in the streamtype definition, where name
is, eg, "lwa" in the example above.
### `auth[].name`
This is the name of the authentication scheme used by other streamtypes
### `auth[].streamtype`
This is the auth streamtype to be used to refresh the authentication token
### `auth[].blob`
This is the auth blob index the authentication token is stored into and retreived
from
### `s`
These are an array of policies for the supported stream type names.
@ -308,6 +336,11 @@ policy is applied.
The name of the trust store described in the `trust_stores` section to apply
to validate the remote server cert.
### `use_auth`
Indicate that the streamtype should use the named auth type from the `auth`
array in the policy
### `server_cert`
**SERVER ONLY**: subject to change... the name of the x.509 cert that is the

View file

@ -100,7 +100,12 @@ static const char * const lejp_tokens_policy[] = {
"s[].*.mqtt_will_qos",
"s[].*.mqtt_will_retain",
"s[].*.swake_validity",
"s[].*.use_auth",
"s[].*",
"auth[].name",
"auth[].streamtype",
"auth[].blob",
"auth[]",
};
typedef enum {
@ -175,7 +180,12 @@ typedef enum {
LSSPPT_MQTT_WILL_QOS,
LSSPPT_MQTT_WILL_RETAIN,
LSSPPT_SWAKE_VALIDITY,
LSSPPT_USE_AUTH,
LSSPPT_STREAMTYPES,
LSSPPT_AUTH_NAME,
LSSPPT_AUTH_STREAMTYPE,
LSSPPT_AUTH_BLOB,
LSSPPT_AUTH,
} policy_token_t;
@ -188,9 +198,10 @@ static uint8_t sizes[] = {
sizeof(lws_ss_x509_t),
sizeof(lws_ss_trust_store_t),
sizeof(lws_ss_policy_t),
sizeof(lws_ss_auth_t),
};
static const char *protonames[] = {
static const char * const protonames[] = {
"h1", /* LWSSSP_H1 */
"h2", /* LWSSSP_H2 */
"ws", /* LWSSSP_WS */
@ -198,6 +209,24 @@ static const char *protonames[] = {
"raw", /* LWSSSP_RAW */
};
static const lws_ss_auth_t *
lws_ss_policy_find_auth_by_name(struct policy_cb_args *a,
const char *name, size_t len)
{
const lws_ss_auth_t *auth = a->heads[LTY_AUTH].a;
while (auth) {
if (auth->name &&
len == strlen(auth->name) &&
!strncmp(auth->name, name, len))
return auth;
auth = auth->next;
}
return NULL;
}
static signed char
lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason)
{
@ -216,8 +245,8 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason)
backoff_t *bot;
int n = -1;
lwsl_debug("%s: %d %d %s\n", __func__, reason, ctx->path_match - 1,
ctx->path);
// lwsl_debug("%s: %d %d %s\n", __func__, reason, ctx->path_match - 1,
// ctx->path);
switch (ctx->path_match - 1) {
case LSSPPT_RETRY:
@ -233,6 +262,9 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason)
case LSSPPT_STREAMTYPES:
n = LTY_POLICY;
break;
case LSSPPT_AUTH:
n = LTY_AUTH;
break;
}
if (reason == LEJPCB_ARRAY_START &&
@ -241,6 +273,17 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason)
ctx->path_match - 1 == LSSPPT_HTTPRESPMAP))
a->count = 0;
if (reason == LEJPCB_OBJECT_START && n == LTY_AUTH) {
a->curr[n].b = lwsac_use_zero(&a->ac, sizes[n], POL_AC_GRAIN);
if (!a->curr[n].b)
goto oom;
a->curr[n].b->next = a->heads[n].b;
a->heads[n].b = a->curr[n].b;
return 0;
}
if (reason == LEJPCB_ARRAY_END &&
ctx->path_match - 1 == LSSPPT_TRUST_STORES_STACK && !a->count) {
lwsl_err("%s: at least one cert required in trust store\n",
@ -290,7 +333,8 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason)
return 0;
}
if (reason == LEJPCB_PAIR_NAME && n != -1 && n != LTY_TRUSTSTORE) {
if (reason == LEJPCB_PAIR_NAME && n != -1 &&
(n != LTY_TRUSTSTORE && n != LTY_AUTH)) {
p2 = NULL;
if (n == LTY_POLICY) {
@ -574,6 +618,10 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason)
a->curr[LTY_POLICY].p->client_cert = (uint8_t)(atoi(ctx->buf) + 1);
break;
case LSSPPT_AUTH_BLOB:
a->curr[LTY_AUTH].a->blob_index = (uint8_t)atoi(ctx->buf);
break;
case LSSPPT_HTTP_EXPECT:
a->curr[LTY_POLICY].p->u.http.resp_expect = (uint16_t)atoi(ctx->buf);
break;
@ -655,6 +703,16 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason)
case LSSPPT_METADATA:
break;
case LSSPPT_USE_AUTH:
a->curr[LTY_POLICY].p->auth =
lws_ss_policy_find_auth_by_name(a, ctx->buf, ctx->npos);
if (!a->curr[LTY_POLICY].p->auth) {
lws_strnncpy(dotstar, ctx->buf, ctx->npos, sizeof(dotstar));
lwsl_err("%s: unknown auth '%s'\n", __func__, dotstar);
return -1;
}
break;
case LSSPPT_METADATA_ITEM:
pmd = a->curr[LTY_POLICY].p->metadata;
a->curr[LTY_POLICY].p->metadata = lwsac_use_zero(&a->ac,
@ -744,6 +802,14 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason)
pp = (char **)&a->curr[LTY_POLICY].p->u.http.multipart_content_type;
goto string2;
case LSSPPT_AUTH_NAME:
pp = (char **)&a->curr[LTY_AUTH].a->name;
goto string2;
case LSSPPT_AUTH_STREAMTYPE:
pp = (char **)&a->curr[LTY_AUTH].a->streamtype;
goto string2;
case LSSPPT_HTTP_FAIL_REDIRECT:
a->curr[LTY_POLICY].p->u.http.fail_redirect =
reason == LEJPCB_VAL_TRUE;
@ -950,3 +1016,14 @@ lws_ss_policy_get(struct lws_context *context)
return args->heads[LTY_POLICY].p;
}
const lws_ss_auth_t *
lws_ss_auth_get(struct lws_context *context)
{
struct policy_cb_args *args = (struct policy_cb_args *)context->pol_args;
if (!args)
return NULL;
return args->heads[LTY_AUTH].a;
}

View file

@ -312,10 +312,11 @@ typedef struct backoffs {
} backoff_t;
union u {
backoff_t *b;
lws_ss_x509_t *x;
lws_ss_trust_store_t *t;
lws_ss_policy_t *p;
backoff_t *b;
lws_ss_x509_t *x;
lws_ss_trust_store_t *t;
lws_ss_policy_t *p;
lws_ss_auth_t *a;
};
enum {
@ -323,6 +324,7 @@ enum {
LTY_X509,
LTY_TRUSTSTORE,
LTY_POLICY,
LTY_AUTH,
_LTY_COUNT /* always last */
};

View file

@ -175,14 +175,20 @@ static const char * const default_ss_policy =
"]"
"}"
"],"
"\"auth\": [" /* available auth type bindings */
"{"
"\"name\":" "\"lwa\","
"\"streamtype\":" "\"api_amazon_com_lwa\","
"\"blob\":" "0"
"}"
"],"
"\"s\": [" /* the supported stream types */
"{\"api_amazon_com_auth\": {"
"{\"api_amazon_com_lwa\": {"
"\"endpoint\":" "\"api.amazon.com\","
"\"port\":" "443,"
"\"protocol\":" "\"h1\","
"\"http_method\":" "\"POST\","
"\"http_url\":" "\"auth/o2/token\","
"\"plugins\":" "[],"
"\"opportunistic\":" "true,"
"\"tls\":" "true,"
"\"h2q_oflow_txcr\":" "true,"
@ -200,6 +206,7 @@ static const char * const default_ss_policy =
"\"protocol\":" "\"h2\","
"\"http_method\":" "\"GET\","
"\"http_url\":" "\"v20160207/directives\","
"\"use_auth\":" "\"lwa\","
"\"h2q_oflow_txcr\":" "true,"
"\"http_auth_header\":" "\"authorization:\","
"\"http_auth_preamble\":" "\"Bearer \","
@ -207,7 +214,6 @@ static const char * const default_ss_policy =
"\"nailed_up\":" "true,"
"\"long_poll\":" "true,"
"\"retry\":" "\"default\","
"\"plugins\":" "[],"
"\"tls\":" "true,"
"\"tls_trust_store\":" "\"avs_via_starfield\""
"}},"
@ -223,6 +229,7 @@ static const char * const default_ss_policy =
"\"protocol\":" "\"h2\","
"\"http_method\":" "\"POST\","
"\"http_url\":" "\"v20160207/events\","
"\"use_auth\":" "\"lwa\","
"\"opportunistic\":" "true,"
"\"h2q_oflow_txcr\":" "true,"
"\"http_auth_header\":" "\"authorization:\","
@ -233,7 +240,6 @@ static const char * const default_ss_policy =
"\"http_multipart_ss_in\":" "true,"
"\"rideshare\":" "\"avs_audio\","
"\"retry\":" "\"default\","
"\"plugins\":" "[],"
"\"tls\":" "true,"
"\"tls_trust_store\":" "\"avs_via_starfield\""
"}},"
@ -243,7 +249,7 @@ static const char * const default_ss_policy =
"\"protocol\":" "\"h2\","
"\"http_method\":" "\"POST\","
"\"http_url\":" "\"v20160207/events\","
"\"plugins\":" "[],"
"\"use_auth\":" "\"lwa\","
"\"tls\":" "true,"
"\"h2q_oflow_txcr\":" "true,"
"\"http_auth_header\":" "\"authorization:\","

View file

@ -151,14 +151,20 @@ static const char * const default_ss_policy =
"]"
"}"
"],"
"\"auth\": [" /* available auth type bindings */
"{"
"\"name\":" "\"lwa\","
"\"streamtype\":" "\"api_amazon_com_lwa\","
"\"blob\":" "0"
"}"
"],"
"\"s\": [" /* the supported stream types */
"{\"api_amazon_com_auth\": {"
"{\"api_amazon_com_lwa\": {"
"\"endpoint\":" "\"api.amazon.com\","
"\"port\":" "443,"
"\"protocol\":" "\"h1\","
"\"http_method\":" "\"POST\","
"\"http_url\":" "\"auth/o2/token\","
"\"plugins\":" "[],"
"\"opportunistic\":" "true,"
"\"tls\":" "true,"
"\"h2q_oflow_txcr\":" "true,"
@ -176,10 +182,10 @@ static const char * const default_ss_policy =
"\"h2q_oflow_txcr\":" "true,"
"\"http_auth_header\":" "\"authorization:\","
"\"http_auth_preamble\":" "\"Bearer \","
"\"use_auth\":" "\"lwa\","
"\"nailed_up\":" "true,"
"\"long_poll\":" "true,"
"\"retry\":" "\"default\","
"\"plugins\":" "[],"
"\"tls\":" "true,"
"\"tls_trust_store\":" "\"avs_via_starfield\""
"}},"
@ -191,6 +197,7 @@ static const char * const default_ss_policy =
"\"http_url\":" "\"v20160207/events\","
"\"http_no_content_length\":" "true,"
"\"h2q_oflow_txcr\":" "true,"
"\"use_auth\":" "\"lwa\","
"\"http_auth_header\":" "\"authorization:\","
"\"http_auth_preamble\":" "\"Bearer \","
"\"http_multipart_name\":" "\"metadata\","
@ -200,7 +207,6 @@ static const char * const default_ss_policy =
#endif
"\"rideshare\":" "\"avs_audio\","
"\"retry\":" "\"default\","
"\"plugins\":" "[],"
"\"tls\":" "true,"
"\"tls_trust_store\":" "\"avs_via_starfield\""
"}},"
@ -211,12 +217,12 @@ static const char * const default_ss_policy =
"\"http_method\":" "\"POST\","
"\"http_url\":" "\"v20160207/events\","
"\"http_no_content_length\":" "true,"
"\"plugins\":" "[],"
"\"tls\":" "true,"
"\"h2q_oflow_txcr\":" "true,"
#if 1
"\"http_multipart_ss_in\":" "true,"
#endif
"\"use_auth\":" "\"lwa\","
"\"http_auth_header\":" "\"authorization:\","
"\"http_auth_preamble\":" "\"Bearer \","
"\"http_multipart_name\":" "\"audio\","
@ -345,6 +351,8 @@ int main(int argc, const char **argv)
nl.notify_cb = app_system_state_nf;
info.register_notifier_list = app_notifier_list;
puts(default_ss_policy);
context = lws_create_context(&info);
if (!context) {
lwsl_err("lws init failed\n");

View file

@ -74,6 +74,7 @@ int main(int argc, const char **argv)
struct lws_context_creation_info info;
size_t json_size = 0, est = 0;
struct lws_context *context;
const lws_ss_auth_t *auth;
char prev[128], curr[128];
int unique_rbo = 0, m, n;
char buf[64], buf1[64];
@ -362,6 +363,7 @@ int main(int argc, const char **argv)
pol = pol->next;
}
/* dump any streamtype's http resp map */
pol = lws_ss_policy_get(context);
@ -406,6 +408,41 @@ int main(int argc, const char **argv)
if (m)
printf(";\n");
/*
* The auth map
*/
auth = lws_ss_auth_get(context);
if (auth)
printf("\nstatic const lws_ss_auth_t ");
prev[0] = '\0';
while (auth) {
lws_snprintf(curr, sizeof(curr), "_ssau_%s",
purify_csymbol(auth->name, buf, sizeof(buf)));
printf("%s = {\n", curr);
if (prev[0])
printf("\t.next = (void *)&%s,\n", prev);
printf("\t.name = \"%s\",\n", auth->name);
printf("\t.streamtype = \"%s\",\n", auth->streamtype);
printf("\t.blob = %d,\n", auth->blob_index);
printf("}");
if (auth->next)
printf(",");
else
printf(";");
printf("\n");
lws_strncpy(prev, curr, sizeof(prev));
auth = auth->next;
}
if (lws_ss_auth_get(context))
printf("\n");
/*
* The streamtypes
*/
@ -440,6 +477,10 @@ int main(int argc, const char **argv)
printf("\t.socks5_proxy = \"%s\",\n",
pol->socks5_proxy);
if (pol->auth)
printf("\t.auth = &_ssau_%s,\n",
purify_csymbol(pol->auth->name, buf, sizeof(buf)));
{
lws_ss_metadata_t *nv = pol->metadata, *last = NULL;

View file

@ -1006,19 +1006,19 @@ static const lws_ss_trust_store_t _ss_ts_le_via_isrg = {
static const lws_ss_metadata_t _md_mintest_xctype = {
.name = "xctype",
.value = (void *)"X-Content-Type:",
.value__may_own_heap = (void *)"X-Content-Type:",
.length = 0,
},
_md_mintest_ctype = {
.next = (void *)&_md_mintest_xctype,
.name = "ctype",
.value = (void *)"Content-Type:",
.value__may_own_heap = (void *)"Content-Type:",
.length = 1,
},
_md_mintest_uptag = {
.next = (void *)&_md_mintest_ctype,
.name = "uptag",
.value = (void *)"X-Upload-Tag:",
.value__may_own_heap = (void *)"X-Upload-Tag:",
.length = 2,
};