diff options
| author | inoguchi <> | 2020-07-27 13:06:13 +0000 |
|---|---|---|
| committer | inoguchi <> | 2020-07-27 13:06:13 +0000 |
| commit | 4526c73922a269ee5bff5d741d80668a622fa9a2 (patch) | |
| tree | 459bf9af208df69cc8014a2b8f9788ee6347e07e /src | |
| parent | f6ca84b2a3b90a14904068e893964e70473f698d (diff) | |
| download | openbsd-4526c73922a269ee5bff5d741d80668a622fa9a2.tar.gz openbsd-4526c73922a269ee5bff5d741d80668a622fa9a2.tar.bz2 openbsd-4526c73922a269ee5bff5d741d80668a622fa9a2.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 | } | ||
