diff options
author | inoguchi <> | 2020-07-27 13:06:13 +0000 |
---|---|---|
committer | inoguchi <> | 2020-07-27 13:06:13 +0000 |
commit | 76210d29c8ce23ac6f0db2610a1cef027179c7a0 (patch) | |
tree | 459bf9af208df69cc8014a2b8f9788ee6347e07e /src | |
parent | 407f7d98a914db77baf1ed3b08e34fc86b3e06bb (diff) | |
download | openbsd-76210d29c8ce23ac6f0db2610a1cef027179c7a0.tar.gz openbsd-76210d29c8ce23ac6f0db2610a1cef027179c7a0.tar.bz2 openbsd-76210d29c8ce23ac6f0db2610a1cef027179c7a0.zip |
Add function prototype and move sub functions to bottom
Diffstat (limited to 'src')
-rw-r--r-- | src/usr.bin/openssl/s_server.c | 395 |
1 files changed, 197 insertions, 198 deletions
diff --git a/src/usr.bin/openssl/s_server.c b/src/usr.bin/openssl/s_server.c index ebabd41d3e..eb5f62ed56 100644 --- a/src/usr.bin/openssl/s_server.c +++ b/src/usr.bin/openssl/s_server.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: s_server.c,v 1.41 2020/07/27 12:29:51 inoguchi Exp $ */ | 1 | /* $OpenBSD: s_server.c,v 1.42 2020/07/27 13:06:13 inoguchi Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -177,21 +177,22 @@ | |||
177 | #include "s_apps.h" | 177 | #include "s_apps.h" |
178 | #include "timeouts.h" | 178 | #include "timeouts.h" |
179 | 179 | ||
180 | static void s_server_init(void); | ||
181 | static void sv_usage(void); | ||
182 | static void print_stats(BIO *bp, SSL_CTX *ctx); | ||
180 | static int sv_body(char *hostname, int s, unsigned char *context); | 183 | static int sv_body(char *hostname, int s, unsigned char *context); |
181 | static int www_body(char *hostname, int s, unsigned char *context); | ||
182 | static void close_accept_socket(void); | 184 | static void close_accept_socket(void); |
183 | static void sv_usage(void); | ||
184 | static int init_ssl_connection(SSL *s); | 185 | static int init_ssl_connection(SSL *s); |
185 | static void print_stats(BIO *bp, SSL_CTX *ctx); | ||
186 | static int | ||
187 | generate_session_id(const SSL *ssl, unsigned char *id, | ||
188 | unsigned int *id_len); | ||
189 | #ifndef OPENSSL_NO_DH | 186 | #ifndef OPENSSL_NO_DH |
190 | static DH *load_dh_param(const char *dhfile); | 187 | static DH *load_dh_param(const char *dhfile); |
191 | #endif | 188 | #endif |
192 | 189 | static int www_body(char *hostname, int s, unsigned char *context); | |
193 | static void s_server_init(void); | 190 | static int generate_session_id(const SSL *ssl, unsigned char *id, |
194 | 191 | unsigned int *id_len); | |
192 | static int ssl_servername_cb(SSL *s, int *ad, void *arg); | ||
193 | static int cert_status_cb(SSL * s, void *arg); | ||
194 | static int alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen, | ||
195 | const unsigned char *in, unsigned int inlen, void *arg); | ||
195 | /* static int load_CA(SSL_CTX *ctx, char *file);*/ | 196 | /* static int load_CA(SSL_CTX *ctx, char *file);*/ |
196 | 197 | ||
197 | #define BUFSIZZ 16*1024 | 198 | #define BUFSIZZ 16*1024 |
@@ -205,7 +206,9 @@ static int s_server_session_id_context = 1; /* anything will do */ | |||
205 | static SSL_CTX *ctx = NULL; | 206 | static SSL_CTX *ctx = NULL; |
206 | static SSL_CTX *ctx2 = NULL; | 207 | static SSL_CTX *ctx2 = NULL; |
207 | static BIO *bio_s_out = NULL; | 208 | static BIO *bio_s_out = NULL; |
208 | static int cert_status_cb(SSL * s, void *arg); | 209 | |
210 | static int local_argc = 0; | ||
211 | static char **local_argv; | ||
209 | 212 | ||
210 | /* This is a context that we pass to callbacks */ | 213 | /* This is a context that we pass to callbacks */ |
211 | typedef struct tlsextctx_st { | 214 | typedef struct tlsextctx_st { |
@@ -224,6 +227,12 @@ typedef struct tlsextstatusctx_st { | |||
224 | int verbose; | 227 | int verbose; |
225 | } tlsextstatusctx; | 228 | } tlsextstatusctx; |
226 | 229 | ||
230 | /* This the context that we pass to alpn_cb */ | ||
231 | typedef struct tlsextalpnctx_st { | ||
232 | unsigned char *data; | ||
233 | unsigned short len; | ||
234 | } tlsextalpnctx; | ||
235 | |||
227 | static struct { | 236 | static struct { |
228 | char *alpn_in; | 237 | char *alpn_in; |
229 | char *npn_in; /* Ignored. */ | 238 | char *npn_in; /* Ignored. */ |
@@ -1002,191 +1011,6 @@ sv_usage(void) | |||
1002 | fprintf(stderr, "\n"); | 1011 | fprintf(stderr, "\n"); |
1003 | } | 1012 | } |
1004 | 1013 | ||
1005 | static int local_argc = 0; | ||
1006 | static char **local_argv; | ||
1007 | |||
1008 | static int | ||
1009 | ssl_servername_cb(SSL *s, int *ad, void *arg) | ||
1010 | { | ||
1011 | tlsextctx *p = (tlsextctx *) arg; | ||
1012 | const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); | ||
1013 | if (servername && p->biodebug) | ||
1014 | BIO_printf(p->biodebug, "Hostname in TLS extension: \"%s\"\n", servername); | ||
1015 | |||
1016 | if (!p->servername) | ||
1017 | return SSL_TLSEXT_ERR_NOACK; | ||
1018 | |||
1019 | if (servername) { | ||
1020 | if (strcmp(servername, p->servername)) | ||
1021 | return p->extension_error; | ||
1022 | if (ctx2) { | ||
1023 | BIO_printf(p->biodebug, "Switching server context.\n"); | ||
1024 | SSL_set_SSL_CTX(s, ctx2); | ||
1025 | } | ||
1026 | } | ||
1027 | return SSL_TLSEXT_ERR_OK; | ||
1028 | } | ||
1029 | |||
1030 | /* Certificate Status callback. This is called when a client includes a | ||
1031 | * certificate status request extension. | ||
1032 | * | ||
1033 | * This is a simplified version. It examines certificates each time and | ||
1034 | * makes one OCSP responder query for each request. | ||
1035 | * | ||
1036 | * A full version would store details such as the OCSP certificate IDs and | ||
1037 | * minimise the number of OCSP responses by caching them until they were | ||
1038 | * considered "expired". | ||
1039 | */ | ||
1040 | |||
1041 | static int | ||
1042 | cert_status_cb(SSL *s, void *arg) | ||
1043 | { | ||
1044 | tlsextstatusctx *srctx = arg; | ||
1045 | BIO *err = srctx->err; | ||
1046 | char *host = NULL, *port = NULL, *path = NULL; | ||
1047 | int use_ssl; | ||
1048 | unsigned char *rspder = NULL; | ||
1049 | int rspderlen; | ||
1050 | STACK_OF(OPENSSL_STRING) *aia = NULL; | ||
1051 | X509 *x = NULL; | ||
1052 | X509_STORE_CTX inctx; | ||
1053 | X509_OBJECT obj; | ||
1054 | OCSP_REQUEST *req = NULL; | ||
1055 | OCSP_RESPONSE *resp = NULL; | ||
1056 | OCSP_CERTID *id = NULL; | ||
1057 | STACK_OF(X509_EXTENSION) *exts; | ||
1058 | int ret = SSL_TLSEXT_ERR_NOACK; | ||
1059 | int i; | ||
1060 | |||
1061 | if (srctx->verbose) | ||
1062 | BIO_puts(err, "cert_status: callback called\n"); | ||
1063 | /* Build up OCSP query from server certificate */ | ||
1064 | x = SSL_get_certificate(s); | ||
1065 | aia = X509_get1_ocsp(x); | ||
1066 | if (aia) { | ||
1067 | if (!OCSP_parse_url(sk_OPENSSL_STRING_value(aia, 0), | ||
1068 | &host, &port, &path, &use_ssl)) { | ||
1069 | BIO_puts(err, "cert_status: can't parse AIA URL\n"); | ||
1070 | goto err; | ||
1071 | } | ||
1072 | if (srctx->verbose) | ||
1073 | BIO_printf(err, "cert_status: AIA URL: %s\n", | ||
1074 | sk_OPENSSL_STRING_value(aia, 0)); | ||
1075 | } else { | ||
1076 | if (!srctx->host) { | ||
1077 | BIO_puts(srctx->err, "cert_status: no AIA and no default responder URL\n"); | ||
1078 | goto done; | ||
1079 | } | ||
1080 | host = srctx->host; | ||
1081 | path = srctx->path; | ||
1082 | port = srctx->port; | ||
1083 | use_ssl = srctx->use_ssl; | ||
1084 | } | ||
1085 | |||
1086 | if (!X509_STORE_CTX_init(&inctx, | ||
1087 | SSL_CTX_get_cert_store(SSL_get_SSL_CTX(s)), | ||
1088 | NULL, NULL)) | ||
1089 | goto err; | ||
1090 | if (X509_STORE_get_by_subject(&inctx, X509_LU_X509, | ||
1091 | X509_get_issuer_name(x), &obj) <= 0) { | ||
1092 | BIO_puts(err, "cert_status: Can't retrieve issuer certificate.\n"); | ||
1093 | X509_STORE_CTX_cleanup(&inctx); | ||
1094 | goto done; | ||
1095 | } | ||
1096 | req = OCSP_REQUEST_new(); | ||
1097 | if (!req) | ||
1098 | goto err; | ||
1099 | id = OCSP_cert_to_id(NULL, x, obj.data.x509); | ||
1100 | X509_free(obj.data.x509); | ||
1101 | X509_STORE_CTX_cleanup(&inctx); | ||
1102 | if (!id) | ||
1103 | goto err; | ||
1104 | if (!OCSP_request_add0_id(req, id)) | ||
1105 | goto err; | ||
1106 | id = NULL; | ||
1107 | /* Add any extensions to the request */ | ||
1108 | SSL_get_tlsext_status_exts(s, &exts); | ||
1109 | for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { | ||
1110 | X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i); | ||
1111 | if (!OCSP_REQUEST_add_ext(req, ext, -1)) | ||
1112 | goto err; | ||
1113 | } | ||
1114 | resp = process_responder(err, req, host, path, port, use_ssl, NULL, | ||
1115 | srctx->timeout); | ||
1116 | if (!resp) { | ||
1117 | BIO_puts(err, "cert_status: error querying responder\n"); | ||
1118 | goto done; | ||
1119 | } | ||
1120 | rspderlen = i2d_OCSP_RESPONSE(resp, &rspder); | ||
1121 | if (rspderlen <= 0) | ||
1122 | goto err; | ||
1123 | SSL_set_tlsext_status_ocsp_resp(s, rspder, rspderlen); | ||
1124 | if (srctx->verbose) { | ||
1125 | BIO_puts(err, "cert_status: ocsp response sent:\n"); | ||
1126 | OCSP_RESPONSE_print(err, resp, 2); | ||
1127 | } | ||
1128 | ret = SSL_TLSEXT_ERR_OK; | ||
1129 | done: | ||
1130 | if (ret != SSL_TLSEXT_ERR_OK) | ||
1131 | ERR_print_errors(err); | ||
1132 | if (aia) { | ||
1133 | free(host); | ||
1134 | free(path); | ||
1135 | free(port); | ||
1136 | X509_email_free(aia); | ||
1137 | } | ||
1138 | if (id) | ||
1139 | OCSP_CERTID_free(id); | ||
1140 | if (req) | ||
1141 | OCSP_REQUEST_free(req); | ||
1142 | if (resp) | ||
1143 | OCSP_RESPONSE_free(resp); | ||
1144 | return ret; | ||
1145 | err: | ||
1146 | ret = SSL_TLSEXT_ERR_ALERT_FATAL; | ||
1147 | goto done; | ||
1148 | } | ||
1149 | |||
1150 | /* This the context that we pass to alpn_cb */ | ||
1151 | typedef struct tlsextalpnctx_st { | ||
1152 | unsigned char *data; | ||
1153 | unsigned short len; | ||
1154 | } tlsextalpnctx; | ||
1155 | |||
1156 | static int | ||
1157 | alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen, | ||
1158 | const unsigned char *in, unsigned int inlen, void *arg) | ||
1159 | { | ||
1160 | tlsextalpnctx *alpn_ctx = arg; | ||
1161 | |||
1162 | if (!s_server_config.quiet) { | ||
1163 | /* We can assume that in is syntactically valid. */ | ||
1164 | unsigned i; | ||
1165 | |||
1166 | BIO_printf(bio_s_out, | ||
1167 | "ALPN protocols advertised by the client: "); | ||
1168 | for (i = 0; i < inlen; ) { | ||
1169 | if (i) | ||
1170 | BIO_write(bio_s_out, ", ", 2); | ||
1171 | BIO_write(bio_s_out, &in[i + 1], in[i]); | ||
1172 | i += in[i] + 1; | ||
1173 | } | ||
1174 | BIO_write(bio_s_out, "\n", 1); | ||
1175 | } | ||
1176 | |||
1177 | if (SSL_select_next_proto((unsigned char**)out, outlen, alpn_ctx->data, | ||
1178 | alpn_ctx->len, in, inlen) != OPENSSL_NPN_NEGOTIATED) | ||
1179 | return (SSL_TLSEXT_ERR_NOACK); | ||
1180 | |||
1181 | if (!s_server_config.quiet) { | ||
1182 | BIO_printf(bio_s_out, "ALPN protocols selected: "); | ||
1183 | BIO_write(bio_s_out, *out, *outlen); | ||
1184 | BIO_write(bio_s_out, "\n", 1); | ||
1185 | } | ||
1186 | |||
1187 | return (SSL_TLSEXT_ERR_OK); | ||
1188 | } | ||
1189 | |||
1190 | int | 1014 | int |
1191 | s_server_main(int argc, char *argv[]) | 1015 | s_server_main(int argc, char *argv[]) |
1192 | { | 1016 | { |
@@ -2343,8 +2167,7 @@ www_body(char *hostname, int s, unsigned char *context) | |||
2343 | 2167 | ||
2344 | #define MAX_SESSION_ID_ATTEMPTS 10 | 2168 | #define MAX_SESSION_ID_ATTEMPTS 10 |
2345 | static int | 2169 | static int |
2346 | generate_session_id(const SSL *ssl, unsigned char *id, | 2170 | generate_session_id(const SSL *ssl, unsigned char *id, unsigned int *id_len) |
2347 | unsigned int *id_len) | ||
2348 | { | 2171 | { |
2349 | unsigned int count = 0; | 2172 | unsigned int count = 0; |
2350 | do { | 2173 | do { |
@@ -2366,3 +2189,179 @@ generate_session_id(const SSL *ssl, unsigned char *id, | |||
2366 | return 0; | 2189 | return 0; |
2367 | return 1; | 2190 | return 1; |
2368 | } | 2191 | } |
2192 | |||
2193 | static int | ||
2194 | ssl_servername_cb(SSL *s, int *ad, void *arg) | ||
2195 | { | ||
2196 | tlsextctx *p = (tlsextctx *) arg; | ||
2197 | const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); | ||
2198 | if (servername && p->biodebug) | ||
2199 | BIO_printf(p->biodebug, "Hostname in TLS extension: \"%s\"\n", servername); | ||
2200 | |||
2201 | if (!p->servername) | ||
2202 | return SSL_TLSEXT_ERR_NOACK; | ||
2203 | |||
2204 | if (servername) { | ||
2205 | if (strcmp(servername, p->servername)) | ||
2206 | return p->extension_error; | ||
2207 | if (ctx2) { | ||
2208 | BIO_printf(p->biodebug, "Switching server context.\n"); | ||
2209 | SSL_set_SSL_CTX(s, ctx2); | ||
2210 | } | ||
2211 | } | ||
2212 | return SSL_TLSEXT_ERR_OK; | ||
2213 | } | ||
2214 | |||
2215 | /* Certificate Status callback. This is called when a client includes a | ||
2216 | * certificate status request extension. | ||
2217 | * | ||
2218 | * This is a simplified version. It examines certificates each time and | ||
2219 | * makes one OCSP responder query for each request. | ||
2220 | * | ||
2221 | * A full version would store details such as the OCSP certificate IDs and | ||
2222 | * minimise the number of OCSP responses by caching them until they were | ||
2223 | * considered "expired". | ||
2224 | */ | ||
2225 | |||
2226 | static int | ||
2227 | cert_status_cb(SSL *s, void *arg) | ||
2228 | { | ||
2229 | tlsextstatusctx *srctx = arg; | ||
2230 | BIO *err = srctx->err; | ||
2231 | char *host = NULL, *port = NULL, *path = NULL; | ||
2232 | int use_ssl; | ||
2233 | unsigned char *rspder = NULL; | ||
2234 | int rspderlen; | ||
2235 | STACK_OF(OPENSSL_STRING) *aia = NULL; | ||
2236 | X509 *x = NULL; | ||
2237 | X509_STORE_CTX inctx; | ||
2238 | X509_OBJECT obj; | ||
2239 | OCSP_REQUEST *req = NULL; | ||
2240 | OCSP_RESPONSE *resp = NULL; | ||
2241 | OCSP_CERTID *id = NULL; | ||
2242 | STACK_OF(X509_EXTENSION) *exts; | ||
2243 | int ret = SSL_TLSEXT_ERR_NOACK; | ||
2244 | int i; | ||
2245 | |||
2246 | if (srctx->verbose) | ||
2247 | BIO_puts(err, "cert_status: callback called\n"); | ||
2248 | /* Build up OCSP query from server certificate */ | ||
2249 | x = SSL_get_certificate(s); | ||
2250 | aia = X509_get1_ocsp(x); | ||
2251 | if (aia) { | ||
2252 | if (!OCSP_parse_url(sk_OPENSSL_STRING_value(aia, 0), | ||
2253 | &host, &port, &path, &use_ssl)) { | ||
2254 | BIO_puts(err, "cert_status: can't parse AIA URL\n"); | ||
2255 | goto err; | ||
2256 | } | ||
2257 | if (srctx->verbose) | ||
2258 | BIO_printf(err, "cert_status: AIA URL: %s\n", | ||
2259 | sk_OPENSSL_STRING_value(aia, 0)); | ||
2260 | } else { | ||
2261 | if (!srctx->host) { | ||
2262 | BIO_puts(srctx->err, "cert_status: no AIA and no default responder URL\n"); | ||
2263 | goto done; | ||
2264 | } | ||
2265 | host = srctx->host; | ||
2266 | path = srctx->path; | ||
2267 | port = srctx->port; | ||
2268 | use_ssl = srctx->use_ssl; | ||
2269 | } | ||
2270 | |||
2271 | if (!X509_STORE_CTX_init(&inctx, | ||
2272 | SSL_CTX_get_cert_store(SSL_get_SSL_CTX(s)), | ||
2273 | NULL, NULL)) | ||
2274 | goto err; | ||
2275 | if (X509_STORE_get_by_subject(&inctx, X509_LU_X509, | ||
2276 | X509_get_issuer_name(x), &obj) <= 0) { | ||
2277 | BIO_puts(err, "cert_status: Can't retrieve issuer certificate.\n"); | ||
2278 | X509_STORE_CTX_cleanup(&inctx); | ||
2279 | goto done; | ||
2280 | } | ||
2281 | req = OCSP_REQUEST_new(); | ||
2282 | if (!req) | ||
2283 | goto err; | ||
2284 | id = OCSP_cert_to_id(NULL, x, obj.data.x509); | ||
2285 | X509_free(obj.data.x509); | ||
2286 | X509_STORE_CTX_cleanup(&inctx); | ||
2287 | if (!id) | ||
2288 | goto err; | ||
2289 | if (!OCSP_request_add0_id(req, id)) | ||
2290 | goto err; | ||
2291 | id = NULL; | ||
2292 | /* Add any extensions to the request */ | ||
2293 | SSL_get_tlsext_status_exts(s, &exts); | ||
2294 | for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { | ||
2295 | X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i); | ||
2296 | if (!OCSP_REQUEST_add_ext(req, ext, -1)) | ||
2297 | goto err; | ||
2298 | } | ||
2299 | resp = process_responder(err, req, host, path, port, use_ssl, NULL, | ||
2300 | srctx->timeout); | ||
2301 | if (!resp) { | ||
2302 | BIO_puts(err, "cert_status: error querying responder\n"); | ||
2303 | goto done; | ||
2304 | } | ||
2305 | rspderlen = i2d_OCSP_RESPONSE(resp, &rspder); | ||
2306 | if (rspderlen <= 0) | ||
2307 | goto err; | ||
2308 | SSL_set_tlsext_status_ocsp_resp(s, rspder, rspderlen); | ||
2309 | if (srctx->verbose) { | ||
2310 | BIO_puts(err, "cert_status: ocsp response sent:\n"); | ||
2311 | OCSP_RESPONSE_print(err, resp, 2); | ||
2312 | } | ||
2313 | ret = SSL_TLSEXT_ERR_OK; | ||
2314 | done: | ||
2315 | if (ret != SSL_TLSEXT_ERR_OK) | ||
2316 | ERR_print_errors(err); | ||
2317 | if (aia) { | ||
2318 | free(host); | ||
2319 | free(path); | ||
2320 | free(port); | ||
2321 | X509_email_free(aia); | ||
2322 | } | ||
2323 | if (id) | ||
2324 | OCSP_CERTID_free(id); | ||
2325 | if (req) | ||
2326 | OCSP_REQUEST_free(req); | ||
2327 | if (resp) | ||
2328 | OCSP_RESPONSE_free(resp); | ||
2329 | return ret; | ||
2330 | err: | ||
2331 | ret = SSL_TLSEXT_ERR_ALERT_FATAL; | ||
2332 | goto done; | ||
2333 | } | ||
2334 | |||
2335 | static int | ||
2336 | alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen, | ||
2337 | const unsigned char *in, unsigned int inlen, void *arg) | ||
2338 | { | ||
2339 | tlsextalpnctx *alpn_ctx = arg; | ||
2340 | |||
2341 | if (!s_server_config.quiet) { | ||
2342 | /* We can assume that in is syntactically valid. */ | ||
2343 | unsigned i; | ||
2344 | |||
2345 | BIO_printf(bio_s_out, | ||
2346 | "ALPN protocols advertised by the client: "); | ||
2347 | for (i = 0; i < inlen; ) { | ||
2348 | if (i) | ||
2349 | BIO_write(bio_s_out, ", ", 2); | ||
2350 | BIO_write(bio_s_out, &in[i + 1], in[i]); | ||
2351 | i += in[i] + 1; | ||
2352 | } | ||
2353 | BIO_write(bio_s_out, "\n", 1); | ||
2354 | } | ||
2355 | |||
2356 | if (SSL_select_next_proto((unsigned char**)out, outlen, alpn_ctx->data, | ||
2357 | alpn_ctx->len, in, inlen) != OPENSSL_NPN_NEGOTIATED) | ||
2358 | return (SSL_TLSEXT_ERR_NOACK); | ||
2359 | |||
2360 | if (!s_server_config.quiet) { | ||
2361 | BIO_printf(bio_s_out, "ALPN protocols selected: "); | ||
2362 | BIO_write(bio_s_out, *out, *outlen); | ||
2363 | BIO_write(bio_s_out, "\n", 1); | ||
2364 | } | ||
2365 | |||
2366 | return (SSL_TLSEXT_ERR_OK); | ||
2367 | } | ||