diff --git a/include/libwebsockets/lws-system.h b/include/libwebsockets/lws-system.h index cef617307..789724c7a 100644 --- a/include/libwebsockets/lws-system.h +++ b/include/libwebsockets/lws-system.h @@ -81,16 +81,25 @@ typedef enum { /* keep system_state_names[] in sync in context.c */ * LWS_SYSTATE_POLICY_VALID */ } lws_system_states_t; +typedef enum { + LWSSYS_AUTH_GET, + LWSSYS_AUTH_TOTAL_LENGTH, + LWSSYS_AUTH_APPEND, + LWSSYS_AUTH_FREE, +} lws_system_auth_op_t; + +typedef int (*lws_system_auth_cb_t)(struct lws_context *context, int idx, + size_t ofs, uint8_t *buf, size_t *plen, + lws_system_auth_op_t set); + typedef struct lws_system_ops { int (*get_info)(lws_system_item_t i, lws_system_arg_t *arg); int (*reboot)(void); int (*set_clock)(lws_usec_t us); - int (*auth)(int idx, uint8_t *buf, size_t *plen, int set); - /**< Systemwide ephemeral auth tokens get or set... set *plen to max - * size for get, will be set to actual size on return of 0, return 1 - * means token is too big for buffer. idx is token index if multiple. - * Auth tokens are potentially large, and should be stored as binary - * and converted to a transport format like hex. */ + lws_system_auth_cb_t auth; + /**< Systemwide auth token management. For set, content may be appended + * incrementally safely. For get, content may be read out in arbitrary + * fragments using \p ofs. */ } lws_system_ops_t; /** @@ -136,6 +145,7 @@ lws_system_get_info(struct lws_context *context, lws_system_item_t item, * * \param context: the lws_context * \param idx: which auth token + * \param ofs: offset in source to copy from * \param buf: where to store result, or NULL * \param buflen: size of buf * \param flags: how to write the result @@ -148,8 +158,8 @@ lws_system_get_info(struct lws_context *context, lws_system_item_t item, * writing anything. *buflen is still set to the size of the auth token. */ LWS_EXTERN LWS_VISIBLE int -lws_system_get_auth(struct lws_context *context, int idx, uint8_t *buf, - size_t buflen, int flags); +lws_system_get_auth(struct lws_context *context, int idx, size_t ofs, + uint8_t *buf, size_t buflen, int flags); /** * lws_system_get_ops() - get ahold of the system ops struct from the context diff --git a/lib/core/private-lib-core.h b/lib/core/private-lib-core.h index 0e798ca34..2883a3e54 100644 --- a/lib/core/private-lib-core.h +++ b/lib/core/private-lib-core.h @@ -309,6 +309,8 @@ struct lws_context { lws_async_dns_t async_dns; #endif + struct lws_buflist *auth_token[2]; + #if defined(LWS_WITH_NETWORK) lws_state_manager_t mgr_system; lws_state_notify_link_t protocols_notify; diff --git a/lib/roles/h2/http2.c b/lib/roles/h2/http2.c index 70a14be61..002dbaf90 100644 --- a/lib/roles/h2/http2.c +++ b/lib/roles/h2/http2.c @@ -2310,7 +2310,7 @@ lws_h2_client_handshake(struct lws *wsi) strcpy((char *)q, "bearer "); - n = lws_system_get_auth(wsi->context, 0, q + 7, + n = lws_system_get_auth(wsi->context, 0, 0, q + 7, lws_ptr_diff(qend, q + 7), wsi->flags & LCCSCF_H2_HEXIFY_AUTH_TOKEN ? LWSSYSGAUTH_HEX : 0); diff --git a/lib/system/system.c b/lib/system/system.c index 13b6619a7..d5b1f09dc 100644 --- a/lib/system/system.c +++ b/lib/system/system.c @@ -24,7 +24,9 @@ #include +#if defined(LWS_WITH_NETWORK) static const char *hex = "0123456789ABCDEF"; +#endif int lws_system_get_info(struct lws_context *context, lws_system_item_t item, @@ -42,20 +44,68 @@ lws_system_get_ops(struct lws_context *context) return context->system_ops; } +#if defined(LWS_WITH_NETWORK) int -lws_system_get_auth(struct lws_context *context, int idx, uint8_t *buf, - size_t buflen, int flags) +lws_system_auth_default_cb(struct lws_context *context, int idx, size_t ofs, + uint8_t *buf, size_t *plen, lws_system_auth_op_t op) +{ + int n; + + if (idx >= (int)LWS_ARRAY_SIZE(context->auth_token)) + return -1; + + switch (op) { + case LWSSYS_AUTH_GET: + if (!context->auth_token[idx]) + return -1; + + if (!buf) /* we just need to tell him that it exists */ + return -2; + + n = lws_buflist_linear_copy(&context->auth_token[idx], ofs, buf, + *plen); + if (n < 0) + return -2; + + *plen = (size_t)n; + + return 0; + + case LWSSYS_AUTH_TOTAL_LENGTH: + *plen = lws_buflist_total_len(&context->auth_token[idx]); + return 0; + + case LWSSYS_AUTH_APPEND: + if (lws_buflist_append_segment(&context->auth_token[idx], buf, + *plen) < 0) + return -1; + + return 0; + + case LWSSYS_AUTH_FREE: + lws_buflist_destroy_all_segments(&context->auth_token[idx]); + return 0; + + default: + break; + } + + return -1; +} + +int +lws_system_get_auth(struct lws_context *context, int idx, size_t ofs, + uint8_t *buf, size_t buflen, int flags) { size_t bl = buflen; uint8_t *p, b; int n; - if (!context->system_ops || !context->system_ops->auth) { - lwsl_err("%s: add auth system op\n", __func__); - return -1; - } - - if (context->system_ops->auth(idx, buf, &buflen, 0) < 0) { + if (!context->system_ops || !context->system_ops->auth) + n = lws_system_auth_default_cb(context, idx, ofs, buf, &buflen, 0); + else + n = context->system_ops->auth(context, idx, ofs, buf, &buflen, 0); + if (n < 0) { if (buf) lwsl_err("%s: auth get failed\n", __func__); return -1; @@ -63,7 +113,8 @@ lws_system_get_auth(struct lws_context *context, int idx, uint8_t *buf, if (buf && (flags & LWSSYSGAUTH_HEX)) { if (bl < (buflen * 2) + 1) { - lwsl_err("%s: auth in hex oversize %d\n", __func__, (int)bl); + lwsl_err("%s: auth in hex oversize %d\n", __func__, + (int)bl); return -1; } @@ -84,4 +135,4 @@ lws_system_get_auth(struct lws_context *context, int idx, uint8_t *buf, return (int)buflen; } - +#endif