From f5d9956c3e2343455a3025b9d38c539b680da8f5 Mon Sep 17 00:00:00 2001 From: David Timber Date: Sat, 13 Nov 2021 22:35:31 +0800 Subject: Doc progress, improve prne_mbedtls_pth_handle() .. * Add param to prne_mbedtls_pth_handle() for returning return value from the function or poll(). --- src/bne.c | 6 +- src/htbt.c | 26 +++++--- src/imap.h | 5 +- src/iset.h | 48 ++++++++++++++- src/libssh2.h | 187 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- src/llist.h | 54 ++++++++++++++++- src/mbedtls.c | 31 ++++++---- src/mbedtls.h | 58 +++++++++++++++--- src/resolv.c | 6 +- 9 files changed, 377 insertions(+), 44 deletions(-) diff --git a/src/bne.c b/src/bne.c index fef86dd..3927760 100644 --- a/src/bne.c +++ b/src/bne.c @@ -2123,7 +2123,8 @@ static bool bne_vhtbt_do_handshake ( &vctx->ssl, mbedtls_ssl_handshake, vctx->fd, - *ev)) + *ev, + NULL)) { return false; } @@ -2771,7 +2772,8 @@ static bool bne_do_vec_htbt (prne_bne_t *ctx) { &vctx.ssl, mbedtls_ssl_close_notify, vctx.fd, - ev)) + ev, + NULL)) { prne_shutdown(vctx.fd, SHUT_RDWR); } diff --git a/src/htbt.c b/src/htbt.c index 4eb2a05..cdaac87 100644 --- a/src/htbt.c +++ b/src/htbt.c @@ -2238,7 +2238,8 @@ static bool htbt_main_slv_setup_f (void *ioctx, pth_event_t ev) { &ctx->ssl, mbedtls_ssl_handshake, ctx->fd, - ev)) + ev, + NULL)) { ret = false; goto END; @@ -2272,7 +2273,8 @@ static void htbt_main_slv_cleanup_f (void *ioctx, pth_event_t ev) { &ctx->ssl, mbedtls_ssl_close_notify, ctx->fd, - ev); + ev, + NULL); shutdown(ctx->fd, SHUT_RDWR); } @@ -2959,11 +2961,14 @@ static bool htbt_lbd_slv_loopchk_f (void *ioctx) { static bool htbt_lbd_slv_setup_f (void *ioctx, pth_event_t ev) { htbt_lbd_client_t *ctx = (htbt_lbd_client_t*)ioctx; - return prne_mbedtls_pth_handle( - &ctx->ssl, - mbedtls_ssl_handshake, - ctx->fd, - ev) && prne_mbedtls_verify_alp( + return + prne_mbedtls_pth_handle( + &ctx->ssl, + mbedtls_ssl_handshake, + ctx->fd, + ev, + NULL) && + prne_mbedtls_verify_alp( ctx->parent->param.lbd_ssl_conf, &ctx->ssl, PRNE_HTBT_TLS_ALP); @@ -2972,7 +2977,12 @@ static bool htbt_lbd_slv_setup_f (void *ioctx, pth_event_t ev) { static void htbt_lbd_slv_cleanup_f (void *ioctx, pth_event_t ev) { htbt_lbd_client_t *ctx = (htbt_lbd_client_t*)ioctx; - prne_mbedtls_pth_handle(&ctx->ssl, mbedtls_ssl_close_notify, ctx->fd, ev); + prne_mbedtls_pth_handle( + &ctx->ssl, + mbedtls_ssl_close_notify, + ctx->fd, + ev, + NULL); prne_shutdown(ctx->fd, SHUT_RDWR); } diff --git a/src/imap.h b/src/imap.h index 3c44267..2f52755 100644 --- a/src/imap.h +++ b/src/imap.h @@ -69,7 +69,8 @@ void prne_free_imap (prne_imap_t *im); * \brief Clear the elements of the integer map object. * \param im The pointer to the integer map object. * \warning The function call may have the exact same effect as - * \c prne_free_imap() but \c prne_free_imap() must always be used. + * \c prne_free_imap() but \c prne_free_imap() must always be used to free the + * resources allocated for the object. */ void prne_imap_clear (prne_imap_t *im); /** @@ -79,6 +80,8 @@ void prne_imap_clear (prne_imap_t *im); * \param val The value of the new tuple. * \return The pointer to the new tuple allocated in the map. The pointer is * valid as long as the map object remains unmodified. + * \retval NULL if a memory allocation has occurred and \c errno is set to + * \c ENOMEM * \note Calling the function invalidates the pointers previously returned by * other functions. */ diff --git a/src/iset.h b/src/iset.h index 3c8118a..4eb8c6c 100644 --- a/src/iset.h +++ b/src/iset.h @@ -1,3 +1,7 @@ +/** \file + * \brief The integer set implementation. + * \note The C equivalent of \c std::set + */ /* * Copyright (c) 2019-2021 David Timber * @@ -25,19 +29,57 @@ #include +/* Alias declaration */ typedef struct prne_iset prne_iset_t; typedef uintptr_t prne_iset_val_t; struct prne_iset { - prne_iset_val_t *arr; - size_t size; + prne_iset_val_t *arr; // The set sorted in ascending order + size_t size; // The size of the set, the number of elements in the array }; +/** + * \brief Initialise the integer set object. + * \param s The pointer to the integer set object. + * \note \p s can be freed using \c prne_free_iset() once initialised. + * \see \c prne_free_iset() + */ void prne_init_iset (prne_iset_t *s); +/** + * \brief Free resources allocated for the integer set object. + * \param s The pointer to the integer set object. + * \see \c prne_init_iset() + */ void prne_free_iset (prne_iset_t *s); - +/** + * \brief Clear the elements of the integer set object. + * \param s The pointer to the integer set object. + * \warning The function call may have the exact same effect as + * \c prne_free_iset() but \c prne_free_iset() must always be used to free the + * resources allocated for the object. + */ void prne_iset_clear (prne_iset_t *s); +/** + * \brief Insert an integer into the integer set object. + * \param s The pointer to the integer set object. + * \param v The integer. + * \retval true if the integer has been inserted into the set. + * \retval false if a memory allocation error has occurred and \c errno is set + * to \c ENOMEM + */ bool prne_iset_insert (prne_iset_t *s, const prne_iset_val_t v); +/** + * \brief Erase the integer from the integer set object. + * \param s The integer set object. + * \param v The integer. + */ void prne_iset_erase (prne_iset_t *s, const prne_iset_val_t v); +/** + * \brief Look up the integer in the integer set object. + * \param s The integer set object. + * \param v The integer. + * \retval true if the integer is in the set. + * \retval false otherwise. + */ bool prne_iset_lookup (prne_iset_t *s, const prne_iset_val_t v); diff --git a/src/libssh2.h b/src/libssh2.h index e46a07f..ea6c8c3 100644 --- a/src/libssh2.h +++ b/src/libssh2.h @@ -1,3 +1,6 @@ +/** \file + * \brief The libssh2 convenience functions. + */ /* * Copyright (c) 2019-2021 David Timber * @@ -28,39 +31,140 @@ #include +/** + * \brief libssh2_session_handshake() wrapper function. + * \param s The libssh2 session object. + * \param fd The open file descriptor for the session. + * \param ev The pth event object to use on poll(). + * \retval 0 on success. + * \retval Non-zero value returned from the library functions or poll() on + * failure. + * \note This is a convenience function that wraps all the operation that + * involves polling and calling the function again. + */ int prne_lssh2_handshake (LIBSSH2_SESSION *s, const int fd, pth_event_t ev); +/** + * \brief libssh2_userauth_password_ex() wrapper function. + * \param s The libssh2 session object. + * \param fd The open file descriptor for the session. + * \param id The user name. + * \param pw The password. + * \param ev The pth event object to use on poll(). + * \retval 0 on success. + * \retval Non-zero value returned from the library functions or poll() on + * failure. + * \note This is a convenience function that wraps all the operation that + * involves polling and calling the function again. + */ int prne_lssh2_ua_pwd ( LIBSSH2_SESSION *s, const int fd, const char *id, const char *pw, pth_event_t ev); +/** + * \brief libssh2_channel_open_session() wrapper function. + * \param s The libssh2 session object. + * \param fd The open file descriptor for the session. + * \param ev The pth event object to use on poll(). + * \param[out] err The pointer to int for an error code on failure. + * \return The new libssh2 channel object on success. + * \retval NULL on failure. The return value of libssh2_session_last_errno() is + * returned via \p err if used. + * \note This is a convenience function that wraps all the operation that + * involves polling and calling the function again. + */ LIBSSH2_CHANNEL *prne_lssh2_open_ch ( LIBSSH2_SESSION *s, const int fd, pth_event_t ev, int *err); +/** + * \brief libssh2_channel_close() wrapper function. + * \param s The libssh2 session object. + * \param c The libssh2 channel object. + * \param fd The open file descriptor for the session. + * \param ev The pth event object to use on poll(). + * \retval 0 on success. + * \retval Non-zero value returned from the library functions or poll() on + * failure. + * \note This is a convenience function that wraps all the operation that + * involves polling and calling the function again. + */ int prne_lssh2_close_ch ( LIBSSH2_SESSION *s, LIBSSH2_CHANNEL *c, const int fd, pth_event_t ev); +/** + * \brief libssh2_channel_wait_closed() wrapper function. + * \param s The libssh2 session object. + * \param c The libssh2 channel object. + * \param fd The open file descriptor for the session. + * \param ev The pth event object to use on poll(). + * \retval 0 on success. + * \retval Non-zero value returned from the library functions or poll() on + * failure. + * \note This is a convenience function that wraps all the operation that + * involves polling and calling the function again. + */ int prne_lssh2_ch_wait_closed ( LIBSSH2_SESSION *s, LIBSSH2_CHANNEL *c, const int fd, pth_event_t ev); +/** + * \brief libssh2_channel_request_pty() wrapper function. + * \param s The libssh2 session object. + * \param c The libssh2 channel object. + * \param fd The open file descriptor for the session. + * \param term + * \param ev The pth event object to use on poll(). + * \retval 0 on success. + * \retval Non-zero value returned from the library functions or poll() on + * failure. + * \note This is a convenience function that wraps all the operation that + * involves polling and calling the function again. + */ int prne_lssh2_ch_req_pty ( LIBSSH2_SESSION *s, LIBSSH2_CHANNEL *c, const int fd, const char *term, pth_event_t ev); +/** + * \brief libssh2_channel_shell() wrapper function. + * \param s The libssh2 session object. + * \param c The libssh2 channel object. + * \param fd The open file descriptor for the session. + * \param ev The pth event object to use on poll(). + * \retval 0 on success. + * \retval Non-zero value returned from the library functions or poll() on + * failure. + * \note This is a convenience function that wraps all the operation that + * involves polling and calling the function again. + */ int prne_lssh2_ch_sh ( LIBSSH2_SESSION *s, LIBSSH2_CHANNEL *c, const int fd, pth_event_t ev); +/** + * \brief libssh2_channel_read() wrapper function. + * \param s The libssh2 session object. + * \param c The libssh2 channel object. + * \param fd The open file descriptor for the session. + * \param s_err The standard error flag. Returns data from the standard error + * stream instead of the standard output stream if pass as \c true . + * \param[out] buf The output buffer. + * \param[in] len The byte length of \p buf . + * \param ev The pth event object to use on poll(). + * \return The actual number of bytes read from the stream and written to \p buf + * or a negative value returned from the library functions or poll() on + * failure. + * \note This is a convenience function that wraps all the operation that + * involves polling and calling the function again. + */ int prne_lssh2_ch_read ( LIBSSH2_SESSION *s, LIBSSH2_CHANNEL *c, @@ -69,6 +173,19 @@ int prne_lssh2_ch_read ( void *buf, const size_t len, pth_event_t ev); +/** + * \brief libssh2_channel_write() wrapper function. + * \param s The libssh2 session object. + * \param c The libssh2 channel object. + * \param fd The open file descriptor for the session. + * \param buf The buffer containing data to write to the standard input stream. + * \param len The byte length of data to write from \p buf . + * \param ev The pth event object to use on poll(). + * \return The actual number of bytes written to the stream or a negative value + * returned from the library functions or poll() on failure. + * \note This is a convenience function that wraps all the operation that + * involves polling and calling the function again. + */ int prne_lssh2_ch_write ( LIBSSH2_SESSION *s, LIBSSH2_CHANNEL *c, @@ -76,6 +193,18 @@ int prne_lssh2_ch_write ( const void *buf, const size_t len, pth_event_t ev); +/** + * \brief libssh2_session_disconnect_ex() wrapper function. + * \param s The libssh2 session object. + * \param c The libssh2 channel object. + * \param fd The open file descriptor for the session. + * \param ev The pth event object to use on poll(). + * \retval 0 on success. + * \retval Non-zero value returned from the library functions or poll() on + * failure. + * \note This is a convenience function that wraps all the operation that + * involves polling and calling the function again. + */ int prne_lssh2_discon ( LIBSSH2_SESSION *s, const int fd, @@ -83,22 +212,66 @@ int prne_lssh2_discon ( const char *desc, const char *lang, pth_event_t ev); +/** + * \brief libssh2_userauth_list() wrapper function. + * \param s The libssh2 session object. + * \param fd The open file descriptor for the session. + * \param username The pointer to the null-terminated user name string. + * \param ev The pth event object to use on poll(). + * \param[out] err The pointer to an \c int for returning an error occurred + * during the function call if any. The \c int will be set to zero if the + * the operation was successful (optional) + * \return The pointer to the internal comma-separated and null-terminated + * string of the authentication methods available for the user. + * \retval NULL if an error has occurred. The \c int at \p err is set to the + * \c errno + * \note This is a convenience function that wraps all the operation that + * involves polling and calling the function again. + */ const char *prne_lssh2_ua_list ( LIBSSH2_SESSION *s, const int fd, const char *username, pth_event_t ev, int *err); +/** + * \brief libssh2_userauth_authenticated() wrapper function. + * \param s The libssh2 session object. + * \param fd The open file descriptor for the session. + * \param ev The pth event object to use on poll(). + * \retval 1 if the session has been authenticated. + * \retval 0 if the session has not been authenticated. + * \retval Negative value returned from the library functions or poll() on + * failure. + * \note This is a convenience function that wraps all the operation that + * involves polling and calling the function again. + */ int prne_lssh2_ua_authd ( LIBSSH2_SESSION *s, const int fd, pth_event_t ev); -/* Workaround for the library's shitty design -* -* Cripples LIBSSH2_SESSION's ability to send() and recv() so that -* the library can't use the fd. This is used to guarantee that *_free() -* functions never return EAGAIN. -*/ -void prne_lssh2_cripple_session (LIBSSH2_SESSION *s); +/** + * \brief Free the libssh2 session object. + * \param s The libssh2 session object. + * \note This is a bullshit-free version of libssh2_session_free(). + * \note The function call has no effect if \p s is passed NULL. + * \see prne_lssh2_cripple_session() + */ void prne_lssh2_free_session (LIBSSH2_SESSION *s); + +/* Workarounds */ +/** + * \brief Cripple the session's IO ability. Used to guarantee that + * \c libssh2_session_free() will never return \c EAGAIN . + * \param s The libssh2 session object. + * \warning This function renders the session unusuable. The function must be + * the last function to call before calling \c libssh2_session_free() to + * free the resources. + * \note This function is used in \c prne_lssh2_free_session() . This function + * is exposed just to cover the cases where it's necessary to cripple the + * session manually. + * \see prne_lssh2_free_session() + * \see libssh2_session_free() + */ +void prne_lssh2_cripple_session (LIBSSH2_SESSION *s); diff --git a/src/llist.h b/src/llist.h index fdd28e3..3303e82 100644 --- a/src/llist.h +++ b/src/llist.h @@ -1,3 +1,7 @@ +/** \file + * \brief The linked-list implementation. + * \note The C equivalent of \c std::list + */ /* * Copyright (c) 2019-2021 David Timber * @@ -25,6 +29,7 @@ #include +/* Forward and alias declarations */ struct prne_llist; struct prne_llist_entry; typedef struct prne_llist prne_llist_t; @@ -41,17 +46,64 @@ struct prne_llist_entry { prne_llist_element_t element; }; +/** + * \brief Initialise the linked-list object. + * \param llist The pointer to the linked-list object. + * \note \p s can be freed using \c prne_free_llist() once initialised. + * \see \c prne_free_llist() + */ void prne_init_llist (prne_llist_t *llist); +/** + * \brief Free resources allocated for the linked-list object. + * \param llist The pointer to the linked-list object. + * \see \c prne_init_llist() + */ void prne_free_llist (prne_llist_t *llist); - +/** + * \brief Clear the elements of the linked-list object. + * \param llist The pointer to the linked-list object. + * \warning The function call may have the exact same effect as + * \c prne_free_llist() but \c prne_free_llist() must always be used to free + * the resources allocated for the object. + */ void prne_llist_clear (prne_llist_t *llist); +/** + * \brief Insert an element after \p entry into the linked-list object. + * \param llist The pointer to the linked-list object. + * \param entry The entry that will precede the new entry (optional) + * \param element The element. + * \return The pointer to the allocated internal entry object for the element. + * \retval NULL if a memory allocation error has occurred and \c errno is set + * to \c ENOMEM + * \note If \p entry is passed NULL, the behaviour of the function is the same + * is that of prne_llist_append() + * \see prne_llist_append() + */ prne_llist_entry_t *prne_llist_insert ( prne_llist_t *llist, prne_llist_entry_t *entry, const prne_llist_element_t element); +/** + * \brief Append an element to the tail of the linked-list object. + * \param llist The pointer to the linked-list object. + * \param element The element. + * \return The pointer to the allocated internal entry object for the element. + * \retval NULL if a memory allocation error has occurred and \c errno is set + * to \c ENOMEM + * \note This function has the same effect as calling \c prne_llist_insert() + * with \c llist->tail + */ prne_llist_entry_t *prne_llist_append ( prne_llist_t *llist, const prne_llist_element_t element); +/** + * \brief Remove an element from the linked-list object. + * \param llist The pointer to the linked-list object. + * \param entry The pointer to the allocated internal entry object for the + * element. + * \returns The next element of the removed element. + * \retval NULL if the element removed was the tail or the head. + */ prne_llist_entry_t *prne_llist_erase ( prne_llist_t *llist, prne_llist_entry_t *entry); diff --git a/src/mbedtls.c b/src/mbedtls.c index d2e0dfa..30c031e 100644 --- a/src/mbedtls.c +++ b/src/mbedtls.c @@ -176,15 +176,19 @@ bool prne_mbedtls_pth_handle ( mbedtls_ssl_context *ssl, int(*mbedtls_f)(mbedtls_ssl_context*), const int fd, - pth_event_t ev) + pth_event_t ev, + int *f_ret_out) { - int pollret; + int f_ret; + bool ret; struct pollfd pfd; pfd.fd = fd; while (true) { - switch (mbedtls_f(ssl)) { + f_ret = mbedtls_f(ssl); + + switch (f_ret) { case MBEDTLS_ERR_SSL_WANT_READ: pfd.events = POLLIN; break; @@ -192,18 +196,23 @@ bool prne_mbedtls_pth_handle ( pfd.events = POLLOUT; break; case 0: - return true; + ret = true; + goto END; default: - return false; + ret = false; + goto END; } - do { - pollret = prne_pth_poll(&pfd, 1, -1, ev); - if (pollret < 0) { - return false; - } - } while (false); + f_ret = prne_pth_poll(&pfd, 1, -1, ev); + if (f_ret < 0) { + ret = false; + goto END; + } } + +END: + prne_chk_assign(f_ret_out, f_ret); + return ret; } bool prne_mbedtls_verify_alp ( diff --git a/src/mbedtls.h b/src/mbedtls.h index ed113f5..a589ed1 100644 --- a/src/mbedtls.h +++ b/src/mbedtls.h @@ -1,3 +1,6 @@ +/** \file + * \brief The MbedTLS utility functions. + */ /* * Copyright (c) 2019-2021 David Timber * @@ -32,6 +35,9 @@ #include #include +/** \def prne_mbedtls_is_nberr + * \brief Test whether \p expr is a non-blocking operation error. + */ #define prne_mbedtls_is_nberr(expr) \ ((expr) == MBEDTLS_ERR_SSL_WANT_READ || \ (expr) == MBEDTLS_ERR_SSL_WANT_WRITE) @@ -45,24 +51,58 @@ int prne_mbedtls_x509_crt_verify_cb ( uint32_t *flags); int prne_mbedtls_ssl_send_cb (void *ctx, const unsigned char *buf, size_t len); int prne_mbedtls_ssl_recv_cb (void *ctx, unsigned char *buf, size_t len); -/* -* Workaround for a bug - getrandom() blocks -*/ +/** + * \brief Workaround for blocking issue - getrandom() blocks. Remove the + * \c mbedtls_platform_entropy_poll() source and add Proone's own entropy + * sources. + * \warning Proone removes the entropy source because the point of Proone using + * TLS is only for obsecurity, not security. Ordinary applications should never + * do this! From Proone's perspective, using \c getrandom() is unacceptable as + * it could block the calling thread. + * https://github.com/ARMmbed/mbedtls/issues/3551 + */ void prne_mbedtls_entropy_init (mbedtls_entropy_context *ctx); -/* Convenience Functions -*/ +/* Convenience functions */ -// Handles mbedtls_ssl_handshake(), mbedtls_ssl_close_notify() +/** + * \brief Process functions like mbedtls_ssl_handshake() and + * mbedtls_ssl_close_notify(), handling non-blocking error on the fly. + * \param ssl The pointer to the SSL context object. + * \param mbedtls_f The MbedTLS function to handle. + * \param fd The open file descriptor for the connection. + * \param ev The event object to poll() with. + * \param[out] f_ret The pointer to an \c int for the value returned from + * \p mbedtls_f (optional) + * \retval true if the function returned zero, meaning successful operation. + * \retval false if the function returned a negative value. + */ bool prne_mbedtls_pth_handle ( mbedtls_ssl_context *ssl, int(*mbedtls_f)(mbedtls_ssl_context*), const int fd, - pth_event_t ev); - + pth_event_t ev, + int *f_ret); +/** + * \brief Find the specified ALP string in the negotiated ALPs. + * \param conf The pointer to the SSL config object. + * \param ctx The pointer to the SSL context object. + * \param alp The pointer to the null-terminated ALP string to look for. + * \retval true if the ALP string is not in the SSL config or the ALP is found + * in the SSL config and is one of the negotiated ALPs for the connection. + * \retval false otherwise - the ALP is configured and not negotiated for the + * connection. + * \note The function assumes that the ALPN is disabled and will return true if + * the ALP is not configured! + */ bool prne_mbedtls_verify_alp ( const mbedtls_ssl_config *conf, const mbedtls_ssl_context *ctx, const char *alp); - +/** + * \brief perror() for MbedTLS errors. + * \param err The MbedTLS error returned from the functions. + * \param s The messsage to print. + * \see mbedtls_strerror() + */ void prne_mbedtls_perror (const int err, const char *s); diff --git a/src/resolv.c b/src/resolv.c index 107a53d..cb0c218 100644 --- a/src/resolv.c +++ b/src/resolv.c @@ -560,7 +560,8 @@ static bool resolv_ensure_conn (prne_resolv_t *ctx) { &ctx->ssl.ctx, mbedtls_ssl_handshake, ctx->act_sck_pfd.fd, - ev)) + ev, + NULL)) { if (pth_event_status(ev) != PTH_STATUS_OCCURRED) { pth_event_free(ev, FALSE); @@ -1325,7 +1326,8 @@ static void resolv_proc_close (prne_resolv_t *ctx) { &ctx->ssl.ctx, mbedtls_ssl_close_notify, ctx->act_sck_pfd.fd, - ev); + ev, + NULL); resolv_close_sck(ctx, ret ? NULL : &RESOLV_CONN_ERR_PAUSE, !ret); pth_event_free(ev, FALSE); -- cgit