bf_prefix.c revision 1.1.1.1
1/* 2 * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10#include <stdio.h> 11#include <string.h> 12#include <errno.h> 13#include <openssl/bio.h> 14#include "apps.h" 15 16static int prefix_write(BIO *b, const char *out, size_t outl, 17 size_t *numwritten); 18static int prefix_read(BIO *b, char *buf, size_t size, size_t *numread); 19static int prefix_puts(BIO *b, const char *str); 20static int prefix_gets(BIO *b, char *str, int size); 21static long prefix_ctrl(BIO *b, int cmd, long arg1, void *arg2); 22static int prefix_create(BIO *b); 23static int prefix_destroy(BIO *b); 24static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp); 25 26static BIO_METHOD *prefix_meth = NULL; 27 28BIO_METHOD *apps_bf_prefix(void) 29{ 30 if (prefix_meth == NULL) { 31 if ((prefix_meth = 32 BIO_meth_new(BIO_TYPE_FILTER, "Prefix filter")) == NULL 33 || !BIO_meth_set_create(prefix_meth, prefix_create) 34 || !BIO_meth_set_destroy(prefix_meth, prefix_destroy) 35 || !BIO_meth_set_write_ex(prefix_meth, prefix_write) 36 || !BIO_meth_set_read_ex(prefix_meth, prefix_read) 37 || !BIO_meth_set_puts(prefix_meth, prefix_puts) 38 || !BIO_meth_set_gets(prefix_meth, prefix_gets) 39 || !BIO_meth_set_ctrl(prefix_meth, prefix_ctrl) 40 || !BIO_meth_set_callback_ctrl(prefix_meth, prefix_callback_ctrl)) { 41 BIO_meth_free(prefix_meth); 42 prefix_meth = NULL; 43 } 44 } 45 return prefix_meth; 46} 47 48typedef struct prefix_ctx_st { 49 char *prefix; 50 int linestart; /* flag to indicate we're at the line start */ 51} PREFIX_CTX; 52 53static int prefix_create(BIO *b) 54{ 55 PREFIX_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); 56 57 if (ctx == NULL) 58 return 0; 59 60 ctx->prefix = NULL; 61 ctx->linestart = 1; 62 BIO_set_data(b, ctx); 63 BIO_set_init(b, 1); 64 return 1; 65} 66 67static int prefix_destroy(BIO *b) 68{ 69 PREFIX_CTX *ctx = BIO_get_data(b); 70 71 OPENSSL_free(ctx->prefix); 72 OPENSSL_free(ctx); 73 return 1; 74} 75 76static int prefix_read(BIO *b, char *in, size_t size, size_t *numread) 77{ 78 return BIO_read_ex(BIO_next(b), in, size, numread); 79} 80 81static int prefix_write(BIO *b, const char *out, size_t outl, 82 size_t *numwritten) 83{ 84 PREFIX_CTX *ctx = BIO_get_data(b); 85 86 if (ctx == NULL) 87 return 0; 88 89 /* If no prefix is set or if it's empty, we've got nothing to do here */ 90 if (ctx->prefix == NULL || *ctx->prefix == '\0') { 91 /* We do note if what comes next will be a new line, though */ 92 if (outl > 0) 93 ctx->linestart = (out[outl-1] == '\n'); 94 return BIO_write_ex(BIO_next(b), out, outl, numwritten); 95 } 96 97 *numwritten = 0; 98 99 while (outl > 0) { 100 size_t i; 101 char c; 102 103 /* If we know that we're at the start of the line, output the prefix */ 104 if (ctx->linestart) { 105 size_t dontcare; 106 107 if (!BIO_write_ex(BIO_next(b), ctx->prefix, strlen(ctx->prefix), 108 &dontcare)) 109 return 0; 110 ctx->linestart = 0; 111 } 112 113 /* Now, go look for the next LF, or the end of the string */ 114 for (i = 0, c = '\0'; i < outl && (c = out[i]) != '\n'; i++) 115 continue; 116 if (c == '\n') 117 i++; 118 119 /* Output what we found so far */ 120 while (i > 0) { 121 size_t num = 0; 122 123 if (!BIO_write_ex(BIO_next(b), out, i, &num)) 124 return 0; 125 out += num; 126 outl -= num; 127 *numwritten += num; 128 i -= num; 129 } 130 131 /* If we found a LF, what follows is a new line, so take note */ 132 if (c == '\n') 133 ctx->linestart = 1; 134 } 135 136 return 1; 137} 138 139static long prefix_ctrl(BIO *b, int cmd, long num, void *ptr) 140{ 141 long ret = 0; 142 143 switch (cmd) { 144 case PREFIX_CTRL_SET_PREFIX: 145 { 146 PREFIX_CTX *ctx = BIO_get_data(b); 147 148 if (ctx == NULL) 149 break; 150 151 OPENSSL_free(ctx->prefix); 152 ctx->prefix = OPENSSL_strdup((const char *)ptr); 153 ret = ctx->prefix != NULL; 154 } 155 break; 156 default: 157 if (BIO_next(b) != NULL) 158 ret = BIO_ctrl(BIO_next(b), cmd, num, ptr); 159 break; 160 } 161 return ret; 162} 163 164static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) 165{ 166 return BIO_callback_ctrl(BIO_next(b), cmd, fp); 167} 168 169static int prefix_gets(BIO *b, char *buf, int size) 170{ 171 return BIO_gets(BIO_next(b), buf, size); 172} 173 174static int prefix_puts(BIO *b, const char *str) 175{ 176 return BIO_write(b, str, strlen(str)); 177} 178