]>
Commit | Line | Data |
---|---|---|
39556e63 RL |
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 | ||
16 | static int prefix_write(BIO *b, const char *out, size_t outl, | |
17 | size_t *numwritten); | |
18 | static int prefix_read(BIO *b, char *buf, size_t size, size_t *numread); | |
19 | static int prefix_puts(BIO *b, const char *str); | |
20 | static int prefix_gets(BIO *b, char *str, int size); | |
21 | static long prefix_ctrl(BIO *b, int cmd, long arg1, void *arg2); | |
22 | static int prefix_create(BIO *b); | |
23 | static int prefix_destroy(BIO *b); | |
24 | static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp); | |
25 | ||
26 | static BIO_METHOD *prefix_meth = NULL; | |
27 | ||
28 | BIO_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 | ||
48 | typedef struct prefix_ctx_st { | |
49 | char *prefix; | |
50 | int linestart; /* flag to indicate we're at the line start */ | |
51 | } PREFIX_CTX; | |
52 | ||
53 | static 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 | ||
67 | static 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 | ||
76 | static 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 | ||
81 | static 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 | ||
03cb2cc9 | 99 | while (outl > 0) { |
39556e63 RL |
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 */ | |
03cb2cc9 | 114 | for (i = 0, c = '\0'; i < outl && (c = out[i]) != '\n'; i++) |
39556e63 RL |
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; | |
03cb2cc9 | 126 | outl -= num; |
39556e63 RL |
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 | ||
139 | static 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 | ||
164 | static 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 | ||
169 | static int prefix_gets(BIO *b, char *buf, int size) | |
170 | { | |
171 | return BIO_gets(BIO_next(b), buf, size); | |
172 | } | |
173 | ||
174 | static int prefix_puts(BIO *b, const char *str) | |
175 | { | |
176 | return BIO_write(b, str, strlen(str)); | |
177 | } |