mirror of https://github.com/openssl/openssl.git
				
				
				
			BIO: Add BIO_f_prefix(), a text line prefixing filter
Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/10531)
This commit is contained in:
		
							parent
							
								
									a0848daee5
								
							
						
					
					
						commit
						319cee9e2f
					
				|  | @ -0,0 +1,207 @@ | ||||||
|  | /*
 | ||||||
|  |  * Copyright 2018-2019 The OpenSSL Project Authors. All Rights Reserved. | ||||||
|  |  * | ||||||
|  |  * Licensed under the Apache License 2.0 (the "License").  You may not use | ||||||
|  |  * this file except in compliance with the License.  You can obtain a copy | ||||||
|  |  * in the file LICENSE in the source distribution or at | ||||||
|  |  * https://www.openssl.org/source/license.html
 | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include "bio_local.h" | ||||||
|  | 
 | ||||||
|  | static int prefix_write(BIO *b, const char *out, size_t outl, | ||||||
|  |                         size_t *numwritten); | ||||||
|  | static int prefix_read(BIO *b, char *buf, size_t size, size_t *numread); | ||||||
|  | static int prefix_puts(BIO *b, const char *str); | ||||||
|  | static int prefix_gets(BIO *b, char *str, int size); | ||||||
|  | static long prefix_ctrl(BIO *b, int cmd, long arg1, void *arg2); | ||||||
|  | static int prefix_create(BIO *b); | ||||||
|  | static int prefix_destroy(BIO *b); | ||||||
|  | static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp); | ||||||
|  | 
 | ||||||
|  | static const BIO_METHOD prefix_meth = { | ||||||
|  |     BIO_TYPE_BUFFER, | ||||||
|  |     "prefix", | ||||||
|  |     prefix_write, | ||||||
|  |     NULL, | ||||||
|  |     prefix_read, | ||||||
|  |     NULL, | ||||||
|  |     prefix_puts, | ||||||
|  |     prefix_gets, | ||||||
|  |     prefix_ctrl, | ||||||
|  |     prefix_create, | ||||||
|  |     prefix_destroy, | ||||||
|  |     prefix_callback_ctrl, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const BIO_METHOD *BIO_f_prefix(void) | ||||||
|  | { | ||||||
|  |     return &prefix_meth; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | typedef struct prefix_ctx_st { | ||||||
|  |     char *prefix;              /* Text prefix, given by user */ | ||||||
|  |     unsigned int indent;       /* Indentation amount, given by user */ | ||||||
|  | 
 | ||||||
|  |     int linestart;             /* flag to indicate we're at the line start */ | ||||||
|  | } PREFIX_CTX; | ||||||
|  | 
 | ||||||
|  | static int prefix_create(BIO *b) | ||||||
|  | { | ||||||
|  |     PREFIX_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); | ||||||
|  | 
 | ||||||
|  |     if (ctx == NULL) | ||||||
|  |         return 0; | ||||||
|  | 
 | ||||||
|  |     ctx->prefix = NULL; | ||||||
|  |     ctx->indent = 0; | ||||||
|  |     ctx->linestart = 1; | ||||||
|  |     BIO_set_data(b, ctx); | ||||||
|  |     BIO_set_init(b, 1); | ||||||
|  |     return 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int prefix_destroy(BIO *b) | ||||||
|  | { | ||||||
|  |     PREFIX_CTX *ctx = BIO_get_data(b); | ||||||
|  | 
 | ||||||
|  |     OPENSSL_free(ctx->prefix); | ||||||
|  |     OPENSSL_free(ctx); | ||||||
|  |     return 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int prefix_read(BIO *b, char *in, size_t size, size_t *numread) | ||||||
|  | { | ||||||
|  |     return BIO_read_ex(BIO_next(b), in, size, numread); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int prefix_write(BIO *b, const char *out, size_t outl, | ||||||
|  |                         size_t *numwritten) | ||||||
|  | { | ||||||
|  |     PREFIX_CTX *ctx = BIO_get_data(b); | ||||||
|  | 
 | ||||||
|  |     if (ctx == NULL) | ||||||
|  |         return 0; | ||||||
|  | 
 | ||||||
|  |     /*
 | ||||||
|  |      * If no prefix is set or if it's empty, and no indentation amount is set, | ||||||
|  |      * we've got nothing to do here | ||||||
|  |      */ | ||||||
|  |     if ((ctx->prefix == NULL || *ctx->prefix == '\0') | ||||||
|  |         && ctx->indent == 0) { | ||||||
|  |         /*
 | ||||||
|  |          * We do note if what comes next will be a new line, though, so we're | ||||||
|  |          * prepared to handle prefix and indentation the next time around. | ||||||
|  |          */ | ||||||
|  |         if (outl > 0) | ||||||
|  |             ctx->linestart = (out[outl-1] == '\n'); | ||||||
|  |         return BIO_write_ex(BIO_next(b), out, outl, numwritten); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     *numwritten = 0; | ||||||
|  | 
 | ||||||
|  |     while (outl > 0) { | ||||||
|  |         size_t i; | ||||||
|  |         char c; | ||||||
|  | 
 | ||||||
|  |         /*
 | ||||||
|  |          * If we know that we're at the start of the line, output prefix and | ||||||
|  |          * indentation. | ||||||
|  |          */ | ||||||
|  |         if (ctx->linestart) { | ||||||
|  |             size_t dontcare; | ||||||
|  | 
 | ||||||
|  |             if (ctx->prefix != NULL | ||||||
|  |                 && !BIO_write_ex(BIO_next(b), ctx->prefix, strlen(ctx->prefix), | ||||||
|  |                                  &dontcare)) | ||||||
|  |                 return 0; | ||||||
|  |             BIO_printf(BIO_next(b), "%*s", ctx->indent, ""); | ||||||
|  |             ctx->linestart = 0; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /* Now, go look for the next LF, or the end of the string */ | ||||||
|  |         for (i = 0, c = '\0'; i < outl && (c = out[i]) != '\n'; i++) | ||||||
|  |             continue; | ||||||
|  |         if (c == '\n') | ||||||
|  |             i++; | ||||||
|  | 
 | ||||||
|  |         /* Output what we found so far */ | ||||||
|  |         while (i > 0) { | ||||||
|  |             size_t num = 0; | ||||||
|  | 
 | ||||||
|  |             if (!BIO_write_ex(BIO_next(b), out, i, &num)) | ||||||
|  |                 return 0; | ||||||
|  |             out += num; | ||||||
|  |             outl -= num; | ||||||
|  |             *numwritten += num; | ||||||
|  |             i -= num; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /* If we found a LF, what follows is a new line, so take note */ | ||||||
|  |         if (c == '\n') | ||||||
|  |             ctx->linestart = 1; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static long prefix_ctrl(BIO *b, int cmd, long num, void *ptr) | ||||||
|  | { | ||||||
|  |     long ret = 0; | ||||||
|  |     PREFIX_CTX *ctx = BIO_get_data(b); | ||||||
|  | 
 | ||||||
|  |     if (ctx == NULL) | ||||||
|  |         return -1; | ||||||
|  | 
 | ||||||
|  |     switch (cmd) { | ||||||
|  |     case BIO_CTRL_SET_PREFIX: | ||||||
|  |         OPENSSL_free(ctx->prefix); | ||||||
|  |         if (ptr == NULL) { | ||||||
|  |             ctx->prefix = NULL; | ||||||
|  |             ret = 1; | ||||||
|  |         } else { | ||||||
|  |             ctx->prefix = OPENSSL_strdup((const char *)ptr); | ||||||
|  |             ret = ctx->prefix != NULL; | ||||||
|  |         } | ||||||
|  |         break; | ||||||
|  |     case BIO_CTRL_SET_INDENT: | ||||||
|  |         if (num >= 0) { | ||||||
|  |             ctx->indent = (unsigned int)num; | ||||||
|  |             ret = 1; | ||||||
|  |         } | ||||||
|  |         break; | ||||||
|  |     case BIO_CTRL_GET_INDENT: | ||||||
|  |         ret = (long)ctx->indent; | ||||||
|  |         break; | ||||||
|  |     default: | ||||||
|  |         /* Commands that we intercept before passing them along */ | ||||||
|  |         switch (cmd) { | ||||||
|  |         case BIO_C_FILE_SEEK: | ||||||
|  |         case BIO_CTRL_RESET: | ||||||
|  |             ctx->linestart = 1; | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         if (BIO_next(b) != NULL) | ||||||
|  |             ret = BIO_ctrl(BIO_next(b), cmd, num, ptr); | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) | ||||||
|  | { | ||||||
|  |     return BIO_callback_ctrl(BIO_next(b), cmd, fp); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int prefix_gets(BIO *b, char *buf, int size) | ||||||
|  | { | ||||||
|  |     return BIO_gets(BIO_next(b), buf, size); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int prefix_puts(BIO *b, const char *str) | ||||||
|  | { | ||||||
|  |     return BIO_write(b, str, strlen(str)); | ||||||
|  | } | ||||||
|  | @ -15,4 +15,4 @@ SOURCE[../../libcrypto]=\ | ||||||
| 
 | 
 | ||||||
| # Filters | # Filters | ||||||
| SOURCE[../../libcrypto]=\ | SOURCE[../../libcrypto]=\ | ||||||
|         bf_null.c bf_buff.c bf_lbuf.c bf_nbio.c |         bf_null.c bf_buff.c bf_lbuf.c bf_nbio.c bf_prefix.c | ||||||
|  |  | ||||||
|  | @ -0,0 +1,70 @@ | ||||||
|  | =pod | ||||||
|  | 
 | ||||||
|  | =head1 NAME | ||||||
|  | 
 | ||||||
|  | BIO_f_prefix, BIO_set_prefix, BIO_set_indent, BIO_get_indent | ||||||
|  | - prefix BIO filter | ||||||
|  | 
 | ||||||
|  | =head1 SYNOPSIS | ||||||
|  | 
 | ||||||
|  |  #include <openssl/bio.h> | ||||||
|  | 
 | ||||||
|  |  const BIO_METHOD *BIO_f_prefix(void); | ||||||
|  |  long BIO_set_prefix(BIO *b, const char *prefix); | ||||||
|  |  long BIO_set_indent(BIO *b, long indent); | ||||||
|  |  long BIO_get_indent(BIO *b); | ||||||
|  | 
 | ||||||
|  | =head1 DESCRIPTION | ||||||
|  | 
 | ||||||
|  | BIO_f_cipher() returns the prefix BIO method. This is a filter for | ||||||
|  | text output, where each line gets automatically prefixed and indented | ||||||
|  | according to user input. | ||||||
|  | 
 | ||||||
|  | The prefix and the indentation are combined.  For each line of output | ||||||
|  | going through this filter, the prefix is output first, then the amount | ||||||
|  | of additional spaces indicated by the indentation, and then the line | ||||||
|  | itself. | ||||||
|  | 
 | ||||||
|  | By default, there is no prefix, and indentation is set to 0. | ||||||
|  | 
 | ||||||
|  | BIO_set_prefix() sets the prefix to be used for future lines of | ||||||
|  | text, using I<prefix>.  I<prefix> may be NULL, signifying that there | ||||||
|  | should be no prefix.  If I<prefix> isn't NULL, this function makes a | ||||||
|  | copy of it. | ||||||
|  | 
 | ||||||
|  | BIO_set_indent() sets the indentation to be used for future lines of | ||||||
|  | text, using I<indent>.  Negative values are not allowed. | ||||||
|  | 
 | ||||||
|  | BIO_get_indent() gets the current indentation. | ||||||
|  | 
 | ||||||
|  | =head1 NOTES | ||||||
|  | 
 | ||||||
|  | BIO_set_prefix(), BIO_set_indent() and BIO_get_indent() are | ||||||
|  | implemented as macros. | ||||||
|  | 
 | ||||||
|  | =head1 RETURN VALUES | ||||||
|  | 
 | ||||||
|  | BIO_f_prefix() returns the prefix BIO method. | ||||||
|  | 
 | ||||||
|  | BIO_set_prefix() returns 1 if the prefix was correctly set, or 0 on | ||||||
|  | failure. | ||||||
|  | 
 | ||||||
|  | BIO_set_indent() returns 1 if the prefix was correctly set, or 0 on | ||||||
|  | failure. | ||||||
|  | 
 | ||||||
|  | BIO_get_indent() returns the current indentation. | ||||||
|  | 
 | ||||||
|  | =head1 SEE ALSO | ||||||
|  | 
 | ||||||
|  | L<bio(7)> | ||||||
|  | 
 | ||||||
|  | =head1 COPYRIGHT | ||||||
|  | 
 | ||||||
|  | Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. | ||||||
|  | 
 | ||||||
|  | Licensed under the Apache License 2.0 (the "License").  You may not use | ||||||
|  | this file except in compliance with the License.  You can obtain a copy | ||||||
|  | in the file LICENSE in the source distribution or at | ||||||
|  | L<https://www.openssl.org/source/license.html>. | ||||||
|  | 
 | ||||||
|  | =cut | ||||||
|  | @ -160,6 +160,11 @@ extern "C" { | ||||||
| # define BIO_CTRL_DGRAM_SCTP_WAIT_FOR_DRY       77 | # define BIO_CTRL_DGRAM_SCTP_WAIT_FOR_DRY       77 | ||||||
| # define BIO_CTRL_DGRAM_SCTP_MSG_WAITING        78 | # define BIO_CTRL_DGRAM_SCTP_MSG_WAITING        78 | ||||||
| 
 | 
 | ||||||
|  | /* BIO_f_prefix controls */ | ||||||
|  | # define BIO_CTRL_SET_PREFIX                    79 | ||||||
|  | # define BIO_CTRL_SET_INDENT                    80 | ||||||
|  | # define BIO_CTRL_GET_INDENT                    81 | ||||||
|  | 
 | ||||||
| # ifndef OPENSSL_NO_KTLS | # ifndef OPENSSL_NO_KTLS | ||||||
| #  define BIO_get_ktls_send(b)         \ | #  define BIO_get_ktls_send(b)         \ | ||||||
|      BIO_ctrl(b, BIO_CTRL_GET_KTLS_SEND, 0, NULL) |      BIO_ctrl(b, BIO_CTRL_GET_KTLS_SEND, 0, NULL) | ||||||
|  | @ -552,6 +557,11 @@ int BIO_ctrl_reset_read_request(BIO *b); | ||||||
| # define BIO_dgram_get_mtu_overhead(b) \ | # define BIO_dgram_get_mtu_overhead(b) \ | ||||||
|          (unsigned int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_MTU_OVERHEAD, 0, NULL) |          (unsigned int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_MTU_OVERHEAD, 0, NULL) | ||||||
| 
 | 
 | ||||||
|  | /* ctrl macros for BIO_f_prefix */ | ||||||
|  | # define BIO_set_prefix(b,p) BIO_ctrl((b), BIO_CTRL_SET_PREFIX, 0, (void *)(p)) | ||||||
|  | # define BIO_set_indent(b,i) BIO_ctrl((b), BIO_CTRL_SET_INDENT, (i), NULL) | ||||||
|  | # define BIO_get_indent(b) BIO_ctrl((b), BIO_CTRL_GET_INDENT, 0, NULL) | ||||||
|  | 
 | ||||||
| #define BIO_get_ex_new_index(l, p, newf, dupf, freef) \ | #define BIO_get_ex_new_index(l, p, newf, dupf, freef) \ | ||||||
|     CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, l, p, newf, dupf, freef) |     CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, l, p, newf, dupf, freef) | ||||||
| int BIO_set_ex_data(BIO *bio, int idx, void *data); | int BIO_set_ex_data(BIO *bio, int idx, void *data); | ||||||
|  | @ -630,6 +640,7 @@ const BIO_METHOD *BIO_f_null(void); | ||||||
| const BIO_METHOD *BIO_f_buffer(void); | const BIO_METHOD *BIO_f_buffer(void); | ||||||
| const BIO_METHOD *BIO_f_linebuffer(void); | const BIO_METHOD *BIO_f_linebuffer(void); | ||||||
| const BIO_METHOD *BIO_f_nbio_test(void); | const BIO_METHOD *BIO_f_nbio_test(void); | ||||||
|  | const BIO_METHOD *BIO_f_prefix(void); | ||||||
| # ifndef OPENSSL_NO_DGRAM | # ifndef OPENSSL_NO_DGRAM | ||||||
| const BIO_METHOD *BIO_s_datagram(void); | const BIO_METHOD *BIO_s_datagram(void); | ||||||
| int BIO_dgram_non_fatal_error(int error); | int BIO_dgram_non_fatal_error(int error); | ||||||
|  |  | ||||||
|  | @ -4911,3 +4911,4 @@ i2d_X509_PUBKEY_bio                     ?	3_0_0	EXIST::FUNCTION: | ||||||
| RSA_get0_pss_params                     ?	3_0_0	EXIST::FUNCTION:RSA | RSA_get0_pss_params                     ?	3_0_0	EXIST::FUNCTION:RSA | ||||||
| X509_cmp_timeframe                      ?	3_0_0	EXIST::FUNCTION: | X509_cmp_timeframe                      ?	3_0_0	EXIST::FUNCTION: | ||||||
| OSSL_CMP_MSG_get0_header                ?	3_0_0	EXIST::FUNCTION:CMP | OSSL_CMP_MSG_get0_header                ?	3_0_0	EXIST::FUNCTION:CMP | ||||||
|  | BIO_f_prefix                            ?	3_0_0	EXIST::FUNCTION: | ||||||
|  |  | ||||||
|  | @ -127,6 +127,7 @@ BIO_get_conn_port                       define | ||||||
| BIO_get_conn_ip_family                  define | BIO_get_conn_ip_family                  define | ||||||
| BIO_get_fd                              define | BIO_get_fd                              define | ||||||
| BIO_get_fp                              define | BIO_get_fp                              define | ||||||
|  | BIO_get_indent                          define | ||||||
| BIO_get_info_callback                   define | BIO_get_info_callback                   define | ||||||
| BIO_get_md                              define | BIO_get_md                              define | ||||||
| BIO_get_md_ctx                          define | BIO_get_md_ctx                          define | ||||||
|  | @ -158,12 +159,14 @@ BIO_set_conn_port                       define | ||||||
| BIO_set_conn_ip_family                  define | BIO_set_conn_ip_family                  define | ||||||
| BIO_set_fd                              define | BIO_set_fd                              define | ||||||
| BIO_set_fp                              define | BIO_set_fp                              define | ||||||
|  | BIO_set_indent                          define | ||||||
| BIO_set_info_callback                   define | BIO_set_info_callback                   define | ||||||
| BIO_set_md                              define | BIO_set_md                              define | ||||||
| BIO_set_mem_buf                         define | BIO_set_mem_buf                         define | ||||||
| BIO_set_mem_eof_return                  define | BIO_set_mem_eof_return                  define | ||||||
| BIO_set_nbio                            define | BIO_set_nbio                            define | ||||||
| BIO_set_nbio_accept                     define | BIO_set_nbio_accept                     define | ||||||
|  | BIO_set_prefix                          define | ||||||
| BIO_set_read_buffer_size                define | BIO_set_read_buffer_size                define | ||||||
| BIO_set_ssl                             define | BIO_set_ssl                             define | ||||||
| BIO_set_ssl_mode                        define | BIO_set_ssl_mode                        define | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue