int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { struct per_session_data__http *pss = (struct per_session_data__http *)user; unsigned char buffer[4096 + LWS_PRE]; unsigned long amount, file_len, sent; char leaf_path[1024]; const char *mimetype; char *other_headers; unsigned char *end, *start; struct timeval tv; unsigned char *p; #ifndef LWS_NO_CLIENT struct per_session_data__http *pss1; struct lws *wsi1; #endif char buf[256]; char b64[64]; int n, m; #ifdef EXTERNAL_POLL struct lws_pollargs *pa = (struct lws_pollargs *)in; #endif switch (reason) { case LWS_CALLBACK_HTTP: lwsl_notice("lws_http_serve: %s\n",in); if (debug_level & LLL_INFO) { dump_handshake_info(wsi); /* dump the individual URI Arg parameters */ n = 0; while (lws_hdr_copy_fragment(wsi, buf, sizeof(buf), WSI_TOKEN_HTTP_URI_ARGS, n) > 0) { lwsl_notice("URI Arg %d: %s\n", ++n, buf); } } { char name[100], rip[50]; lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), name, sizeof(name), rip, sizeof(rip)); sprintf(buf, "%s (%s)", name, rip); lwsl_notice("HTTP connect from %s\n", buf); } if (len < 1) { lws_return_http_status(wsi, HTTP_STATUS_BAD_REQUEST, NULL); goto try_to_reuse; } #ifndef LWS_NO_CLIENT if (!strncmp(in, "/proxytest", 10)) { struct lws_client_connect_info i; char *rootpath = "/"; const char *p = (const char *)in; if (lws_get_child(wsi)) break; pss->client_finished = 0; memset(&i,0, sizeof(i)); i.context = lws_get_context(wsi); i.address = "git.libwebsockets.org"; i.port = 80; i.ssl_connection = 0; if (p[10]) i.path = (char *)in + 10; else i.path = rootpath; i.host = "git.libwebsockets.org"; i.origin = NULL; i.method = "GET"; i.parent_wsi = wsi; i.uri_replace_from = "git.libwebsockets.org/"; i.uri_replace_to = "/proxytest/"; if (!lws_client_connect_via_info(&i)) { lwsl_err("proxy connect fail\n"); break; } break; } #endif #if 1 /* this example server has no concept of directories */ if (strchr((const char *)in + 1, '/')) { lws_return_http_status(wsi, HTTP_STATUS_NOT_ACCEPTABLE, NULL); goto try_to_reuse; } #endif /* if a legal POST URL, let it continue and accept data */ if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) return 0; /* check for the "send a big file by hand" example case */ if (!strcmp((const char *)in, "/leaf.jpg")) { if (strlen(resource_path) > sizeof(leaf_path) - 10) return -1; sprintf(leaf_path, "%s/leaf.jpg", resource_path); /* well, let's demonstrate how to send the hard way */ p = buffer + LWS_PRE; end = p + sizeof(buffer) - LWS_PRE; pss->fd = lws_plat_file_open(wsi, leaf_path, &file_len, LWS_O_RDONLY); if (pss->fd == LWS_INVALID_FILE) { lwsl_err("faild to open file %s\n", leaf_path); return -1; } /* * we will send a big jpeg file, but it could be * anything. Set the Content-Type: appropriately * so the browser knows what to do with it. * * Notice we use the APIs to build the header, which * will do the right thing for HTTP 1/1.1 and HTTP2 * depending on what connection it happens to be working * on */ if (lws_add_http_header_status(wsi, 200, &p, end)) return 1; if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_SERVER, (unsigned char *)"libwebsockets", 13, &p, end)) return 1; if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, (unsigned char *)"image/jpeg", 10, &p, end)) return 1; if (lws_add_http_header_content_length(wsi, file_len, &p, end)) return 1; if (lws_finalize_http_header(wsi, &p, end)) return 1; /* * send the http headers... * this won't block since it's the first payload sent * on the connection since it was established * (too small for partial) * * Notice they are sent using LWS_WRITE_HTTP_HEADERS * which also means you can't send body too in one step, * this is mandated by changes in HTTP2 */ *p = '\0'; lwsl_info("%s\n", buffer + LWS_PRE); n = lws_write(wsi, buffer + LWS_PRE, p - (buffer + LWS_PRE), LWS_WRITE_HTTP_HEADERS); if (n < 0) { lws_plat_file_close(wsi, pss->fd); return -1; } /* * book us a LWS_CALLBACK_HTTP_WRITEABLE callback */ lws_callback_on_writable(wsi); break; } /* if not, send a file the easy way */ if (!strncmp(in, "/cgit-data/", 11)) { in = (char *)in + 11; strcpy(buf, "/usr/share/cgit"); } else strcpy(buf, resource_path); if (strcmp(in, "/")) { if (*((const char *)in) != '/') strcat(buf, "/"); strncat(buf, in, sizeof(buf) - strlen(buf) - 1); } else /* default file to serve */ strcat(buf, "/test.html"); buf[sizeof(buf) - 1] = '\0'; /* refuse to serve files we don't understand */ mimetype = get_mimetype(buf); if (!mimetype) { lwsl_err("Unknown mimetype for %s\n", buf); lws_return_http_status(wsi, HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE, NULL); return -1; } /* demonstrates how to set a cookie on / */ other_headers = leaf_path; p = (unsigned char *)leaf_path; if (!strcmp((const char *)in, "/") && !lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COOKIE)) { /* this isn't very unguessable but it'll do for us */ gettimeofday(&tv, NULL); n = sprintf(b64, "test=LWS_%u_%u_COOKIE;Max-Age=360000", (unsigned int)tv.tv_sec, (unsigned int)tv.tv_usec); if (lws_add_http_header_by_name(wsi, (unsigned char *)"set-cookie:", (unsigned char *)b64, n, &p, (unsigned char *)leaf_path + sizeof(leaf_path))) return 1; } if (lws_is_ssl(wsi) && lws_add_http_header_by_name(wsi, (unsigned char *) "Strict-Transport-Security:", (unsigned char *) "max-age=15768000 ; " "includeSubDomains", 36, &p, (unsigned char *)leaf_path + sizeof(leaf_path))) return 1; n = (char *)p - leaf_path; n = lws_serve_http_file(wsi, buf, mimetype, other_headers, n); if (n < 0 || ((n > 0) && lws_http_transaction_completed(wsi))) return -1; /* error or can't reuse connection: close the socket */ /* * notice that the sending of the file completes asynchronously, * we'll get a LWS_CALLBACK_HTTP_FILE_COMPLETION callback when * it's done */ break; case LWS_CALLBACK_HTTP_BODY: /* create the POST argument parser if not already existing */ if (!pss->spa) { pss->spa = lws_spa_create(wsi, param_names, ARRAY_SIZE(param_names), 1024, file_upload_cb, pss); if (!pss->spa) return -1; pss->filename[0] = '\0'; pss->file_length = 0; } /* let it parse the POST data */ if (lws_spa_process(pss->spa, in, len)) return -1; break; case LWS_CALLBACK_HTTP_BODY_COMPLETION: lwsl_debug("LWS_CALLBACK_HTTP_BODY_COMPLETION\n"); /* * the whole of the sent body arrived, * respond to the client with a redirect to show the * results */ /* call to inform no more payload data coming */ lws_spa_finalize(pss->spa); p = (unsigned char *)pss->result + LWS_PRE; end = p + sizeof(pss->result) - LWS_PRE - 1; p += sprintf((char *)p, "<html><body><h1>Form results (after urldecoding)</h1>" "<table><tr><td>Name</td><td>Length</td><td>Value</td></tr>"); for (n = 0; n < ARRAY_SIZE(param_names); n++) p += snprintf((char *)p, end - p, "<tr><td><b>%s</b></td><td>%d</td><td>%s</td></tr>", param_names[n], lws_spa_get_length(pss->spa, n), lws_spa_get_string(pss->spa, n)); p += snprintf((char *)p, end - p, "</table><br><b>filename:</b> %s, <b>length</b> %ld", pss->filename, pss->file_length); p += snprintf((char *)p, end - p, "</body></html>"); pss->result_len = p - (unsigned char *)(pss->result + LWS_PRE); p = buffer + LWS_PRE; start = p; end = p + sizeof(buffer) - LWS_PRE; if (lws_add_http_header_status(wsi, 200, &p, end)) return 1; if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, (unsigned char *)"text/html", 9, &p, end)) return 1; if (lws_add_http_header_content_length(wsi, pss->result_len, &p, end)) return 1; if (lws_finalize_http_header(wsi, &p, end)) return 1; n = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS); if (n < 0) return 1; n = lws_write(wsi, (unsigned char *)pss->result + LWS_PRE, pss->result_len, LWS_WRITE_HTTP); if (n < 0) return 1; goto try_to_reuse; case LWS_CALLBACK_HTTP_FILE_COMPLETION: goto try_to_reuse; case LWS_CALLBACK_HTTP_WRITEABLE: lwsl_info("LWS_CALLBACK_HTTP_WRITEABLE\n"); if (pss->client_finished) return -1; if (pss->fd == LWS_INVALID_FILE) goto try_to_reuse; #ifndef LWS_NO_CLIENT if (pss->reason_bf & 2) { char *px = buf + LWS_PRE; int lenx = sizeof(buf) - LWS_PRE; /* * our sink is writeable and our source has something * to read. So read a lump of source material of * suitable size to send or what's available, whichever * is the smaller. */ pss->reason_bf &= ~2; wsi1 = lws_get_child(wsi); if (!wsi1) break; if (lws_http_client_read(wsi1, &px, &lenx) < 0) goto bail; if (pss->client_finished) return -1; break; } #endif /* * we can send more of whatever it is we were sending */ sent = 0; do { /* we'd like the send this much */ n = sizeof(buffer) - LWS_PRE; /* but if the peer told us he wants less, we can adapt */ m = lws_get_peer_write_allowance(wsi); /* -1 means not using a protocol that has this info */ if (m == 0) /* right now, peer can't handle anything */ goto later; if (m != -1 && m < n) /* he couldn't handle that much */ n = m; n = lws_plat_file_read(wsi, pss->fd, &amount, buffer + LWS_PRE, n); /* problem reading, close conn */ if (n < 0) { lwsl_err("problem reading file\n"); goto bail; } n = (int)amount; /* sent it all, close conn */ if (n == 0) goto penultimate; /* * To support HTTP2, must take care about preamble space * * identification of when we send the last payload frame * is handled by the library itself if you sent a * content-length header */ m = lws_write(wsi, buffer + LWS_PRE, n, LWS_WRITE_HTTP); if (m < 0) { lwsl_err("write failed\n"); /* write failed, close conn */ goto bail; } if (m) /* while still active, extend timeout */ lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT, 5); sent += m; } while (!lws_send_pipe_choked(wsi) && (sent < 1024 * 1024)); later: lws_callback_on_writable(wsi); break; penultimate: lws_plat_file_close(wsi, pss->fd); pss->fd = LWS_INVALID_FILE; goto try_to_reuse; bail: lws_plat_file_close(wsi, pss->fd); return -1; /* * callback for confirming to continue with client IP appear in * protocol 0 callback since no websocket protocol has been agreed * yet. You can just ignore this if you won't filter on client IP * since the default unhandled callback return is 0 meaning let the * connection continue. */ case LWS_CALLBACK_FILTER_NETWORK_CONNECTION: /* if we returned non-zero from here, we kill the connection */ break; #ifndef LWS_NO_CLIENT case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: { char ctype[64], ctlen = 0; lwsl_err("LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP\n"); p = buffer + LWS_PRE; end = p + sizeof(buffer) - LWS_PRE; if (lws_add_http_header_status(lws_get_parent(wsi), 200, &p, end)) return 1; if (lws_add_http_header_by_token(lws_get_parent(wsi), WSI_TOKEN_HTTP_SERVER, (unsigned char *)"libwebsockets", 13, &p, end)) return 1; ctlen = lws_hdr_copy(wsi, ctype, sizeof(ctype), WSI_TOKEN_HTTP_CONTENT_TYPE); if (ctlen > 0) { if (lws_add_http_header_by_token(lws_get_parent(wsi), WSI_TOKEN_HTTP_CONTENT_TYPE, (unsigned char *)ctype, ctlen, &p, end)) return 1; } #if 0 if (lws_add_http_header_content_length(lws_get_parent(wsi), file_len, &p, end)) return 1; #endif if (lws_finalize_http_header(lws_get_parent(wsi), &p, end)) return 1; *p = '\0'; lwsl_info("%s\n", buffer + LWS_PRE); n = lws_write(lws_get_parent(wsi), buffer + LWS_PRE, p - (buffer + LWS_PRE), LWS_WRITE_HTTP_HEADERS); if (n < 0) return -1; break; } case LWS_CALLBACK_CLOSED_CLIENT_HTTP: //lwsl_err("LWS_CALLBACK_CLOSED_CLIENT_HTTP\n"); return -1; break; case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: //lwsl_err("LWS_CALLBACK_RECEIVE_CLIENT_HTTP: wsi %p\n", wsi); assert(lws_get_parent(wsi)); if (!lws_get_parent(wsi)) break; // lwsl_err("LWS_CALLBACK_RECEIVE_CLIENT_HTTP: wsi %p: sock: %d, parent_wsi: %p, parent_sock:%d, len %d\n", // wsi, lws_get_socket_fd(wsi), // lws_get_parent(wsi), // lws_get_socket_fd(lws_get_parent(wsi)), len); pss1 = lws_wsi_user(lws_get_parent(wsi)); pss1->reason_bf |= 2; lws_callback_on_writable(lws_get_parent(wsi)); break; case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: //lwsl_err("LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ len %d\n", len); assert(lws_get_parent(wsi)); m = lws_write(lws_get_parent(wsi), (unsigned char *)in, len, LWS_WRITE_HTTP); if (m < 0) return -1; break; case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: //lwsl_err("LWS_CALLBACK_COMPLETED_CLIENT_HTTP\n"); assert(lws_get_parent(wsi)); if (!lws_get_parent(wsi)) break; pss1 = lws_wsi_user(lws_get_parent(wsi)); pss1->client_finished = 1; break; #endif /* * callbacks for managing the external poll() array appear in * protocol 0 callback */ case LWS_CALLBACK_LOCK_POLL: /* * lock mutex to protect pollfd state * called before any other POLL related callback * if protecting wsi lifecycle change, len == 1 */ test_server_lock(len); break; case LWS_CALLBACK_UNLOCK_POLL: /* * unlock mutex to protect pollfd state when * called after any other POLL related callback * if protecting wsi lifecycle change, len == 1 */ test_server_unlock(len); break; #ifdef EXTERNAL_POLL case LWS_CALLBACK_ADD_POLL_FD: if (count_pollfds >= max_poll_elements) { lwsl_err("LWS_CALLBACK_ADD_POLL_FD: too many sockets to track\n"); return 1; } fd_lookup[pa->fd] = count_pollfds; pollfds[count_pollfds].fd = pa->fd; pollfds[count_pollfds].events = pa->events; pollfds[count_pollfds++].revents = 0; break; case LWS_CALLBACK_DEL_POLL_FD: if (!--count_pollfds) break; m = fd_lookup[pa->fd]; /* have the last guy take up the vacant slot */ pollfds[m] = pollfds[count_pollfds]; fd_lookup[pollfds[count_pollfds].fd] = m; break; case LWS_CALLBACK_CHANGE_MODE_POLL_FD: pollfds[fd_lookup[pa->fd]].events = pa->events; break; #endif case LWS_CALLBACK_GET_THREAD_ID: /* * if you will call "lws_callback_on_writable" * from a different thread, return the caller thread ID * here so lws can use this information to work out if it * should signal the poll() loop to exit and restart early */ /* return pthread_getthreadid_np(); */ break; #if defined(LWS_USE_POLARSSL) #else #if defined(LWS_USE_MBEDTLS) #else #if defined(LWS_OPENSSL_SUPPORT) case LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION: /* Verify the client certificate */ if (!len || (SSL_get_verify_result((SSL*)in) != X509_V_OK)) { int err = X509_STORE_CTX_get_error((X509_STORE_CTX*)user); int depth = X509_STORE_CTX_get_error_depth((X509_STORE_CTX*)user); const char* msg = X509_verify_cert_error_string(err); lwsl_err("LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION: SSL error: %s (%d), depth: %d\n", msg, err, depth); return 1; } break; #if defined(LWS_HAVE_SSL_CTX_set1_param) case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS: if (crl_path[0]) { /* Enable CRL checking */ X509_VERIFY_PARAM *param = X509_VERIFY_PARAM_new(); X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK); SSL_CTX_set1_param((SSL_CTX*)user, param); X509_STORE *store = SSL_CTX_get_cert_store((SSL_CTX*)user); X509_LOOKUP *lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); n = X509_load_cert_crl_file(lookup, crl_path, X509_FILETYPE_PEM); X509_VERIFY_PARAM_free(param); if (n != 1) { char errbuf[256]; n = ERR_get_error(); lwsl_err("LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS: SSL error: %s (%d)\n", ERR_error_string(n, errbuf), n); return 1; } } break; #endif #endif #endif #endif default: break; } return 0; /* if we're on HTTP1.1 or 2.0, will keep the idle connection alive */ try_to_reuse: if (lws_http_transaction_completed(wsi)) return -1; return 0; }
void tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file, const char *ca_file_inline, const char *ca_path, bool tls_server ) { STACK_OF(X509_INFO) *info_stack = NULL; STACK_OF(X509_NAME) *cert_names = NULL; X509_LOOKUP *lookup = NULL; X509_STORE *store = NULL; X509_NAME *xn = NULL; BIO *in = NULL; int i, added = 0, prev = 0; ASSERT(NULL != ctx); store = SSL_CTX_get_cert_store(ctx->ctx); if (!store) msg(M_SSLERR, "Cannot get certificate store (SSL_CTX_get_cert_store)"); /* Try to add certificates and CRLs from ca_file */ if (ca_file) { if (!strcmp (ca_file, INLINE_FILE_TAG) && ca_file_inline) in = BIO_new_mem_buf ((char *)ca_file_inline, -1); else in = BIO_new_file (ca_file, "r"); if (in) info_stack = PEM_X509_INFO_read_bio (in, NULL, NULL, NULL); if (info_stack) { for (i = 0; i < sk_X509_INFO_num (info_stack); i++) { X509_INFO *info = sk_X509_INFO_value (info_stack, i); if (info->crl) X509_STORE_add_crl (store, info->crl); if (tls_server && !info->x509) { msg (M_SSLERR, "X509 name was missing in TLS mode"); } if (info->x509) { X509_STORE_add_cert (store, info->x509); added++; if (!tls_server) continue; /* Use names of CAs as a client CA list */ if (cert_names == NULL) { cert_names = sk_X509_NAME_new (sk_x509_name_cmp); if (!cert_names) continue; } xn = X509_get_subject_name (info->x509); if (!xn) continue; /* Don't add duplicate CA names */ if (sk_X509_NAME_find (cert_names, xn) == -1) { xn = X509_NAME_dup (xn); if (!xn) continue; sk_X509_NAME_push (cert_names, xn); } } if (tls_server) { int cnum = sk_X509_NAME_num (cert_names); if (cnum != (prev + 1)) { msg (M_WARN, "Cannot load CA certificate file %s (entry %d did not validate)", np(ca_file), added); } prev = cnum; } } sk_X509_INFO_pop_free (info_stack, X509_INFO_free); } if (tls_server) SSL_CTX_set_client_CA_list (ctx->ctx, cert_names); if (!added) msg (M_SSLERR, "Cannot load CA certificate file %s (no entries were read)", np(ca_file)); if (tls_server) { int cnum = sk_X509_NAME_num (cert_names); if (cnum != added) msg (M_SSLERR, "Cannot load CA certificate file %s (only %d of %d entries were valid X509 names)", np(ca_file), cnum, added); } if (in) BIO_free (in); } /* Set a store for certs (CA & CRL) with a lookup on the "capath" hash directory */ if (ca_path) { lookup = X509_STORE_add_lookup (store, X509_LOOKUP_hash_dir ()); if (lookup && X509_LOOKUP_add_dir (lookup, ca_path, X509_FILETYPE_PEM)) msg(M_WARN, "WARNING: experimental option --capath %s", ca_path); else msg(M_SSLERR, "Cannot add lookup at --capath %s", ca_path); #if OPENSSL_VERSION_NUMBER >= 0x00907000L X509_STORE_set_flags (store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); #else msg(M_WARN, "WARNING: this version of OpenSSL cannot handle CRL files in capath"); #endif } }
int MAIN(int argc, char **argv) { ENGINE *e = NULL; int i, ret = 1, badarg = 0; char *CApath = NULL, *CAfile = NULL; char *untfile = NULL, *trustfile = NULL, *crlfile = NULL; STACK_OF(X509) *untrusted = NULL, *trusted = NULL; STACK_OF(X509_CRL) *crls = NULL; X509_STORE *cert_ctx = NULL; X509_LOOKUP *lookup = NULL; X509_VERIFY_PARAM *vpm = NULL; int crl_download = 0; char *engine = NULL; cert_ctx = X509_STORE_new(); if (cert_ctx == NULL) goto end; X509_STORE_set_verify_cb(cert_ctx, cb); ERR_load_crypto_strings(); apps_startup(); if (bio_err == NULL) if ((bio_err = BIO_new(BIO_s_file())) != NULL) BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); if (!load_config(bio_err, NULL)) goto end; argc--; argv++; for (;;) { if (argc >= 1) { if (strcmp(*argv, "-CApath") == 0) { if (argc-- < 1) goto usage; CApath = *(++argv); } else if (strcmp(*argv, "-CAfile") == 0) { if (argc-- < 1) goto usage; CAfile = *(++argv); } else if (args_verify(&argv, &argc, &badarg, bio_err, &vpm)) { if (badarg) goto usage; continue; } else if (strcmp(*argv, "-untrusted") == 0) { if (argc-- < 1) goto usage; untfile = *(++argv); } else if (strcmp(*argv, "-trusted") == 0) { if (argc-- < 1) goto usage; trustfile = *(++argv); } else if (strcmp(*argv, "-CRLfile") == 0) { if (argc-- < 1) goto usage; crlfile = *(++argv); } else if (strcmp(*argv, "-crl_download") == 0) crl_download = 1; #ifndef OPENSSL_NO_ENGINE else if (strcmp(*argv, "-engine") == 0) { if (--argc < 1) goto usage; engine = *(++argv); } #endif else if (strcmp(*argv, "-help") == 0) goto usage; else if (strcmp(*argv, "-verbose") == 0) v_verbose = 1; else if (argv[0][0] == '-') goto usage; else break; argc--; argv++; } else break; } e = setup_engine(bio_err, engine, 0); if (vpm) X509_STORE_set1_param(cert_ctx, vpm); lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_file()); if (lookup == NULL) abort(); if (CAfile) { i = X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM); if (!i) { BIO_printf(bio_err, "Error loading file %s\n", CAfile); ERR_print_errors(bio_err); goto end; } } else X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_hash_dir()); if (lookup == NULL) abort(); if (CApath) { i = X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM); if (!i) { BIO_printf(bio_err, "Error loading directory %s\n", CApath); ERR_print_errors(bio_err); goto end; } } else X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); ERR_clear_error(); if (untfile) { untrusted = load_certs(bio_err, untfile, FORMAT_PEM, NULL, e, "untrusted certificates"); if (!untrusted) goto end; } if (trustfile) { trusted = load_certs(bio_err, trustfile, FORMAT_PEM, NULL, e, "trusted certificates"); if (!trusted) goto end; } if (crlfile) { crls = load_crls(bio_err, crlfile, FORMAT_PEM, NULL, e, "other CRLs"); if (!crls) goto end; } ret = 0; if (crl_download) store_setup_crl_download(cert_ctx); if (argc < 1) { if (1 != check(cert_ctx, NULL, untrusted, trusted, crls, e)) ret = -1; } else { for (i = 0; i < argc; i++) if (1 != check(cert_ctx, argv[i], untrusted, trusted, crls, e)) ret = -1; } usage: if (ret == 1) { BIO_printf(bio_err, "usage: verify [-verbose] [-CApath path] [-CAfile file] [-purpose purpose] [-crl_check]"); BIO_printf(bio_err, " [-no_alt_chains] [-attime timestamp]"); #ifndef OPENSSL_NO_ENGINE BIO_printf(bio_err, " [-engine e]"); #endif BIO_printf(bio_err, " cert1 cert2 ...\n"); BIO_printf(bio_err, "recognized usages:\n"); for (i = 0; i < X509_PURPOSE_get_count(); i++) { X509_PURPOSE *ptmp; ptmp = X509_PURPOSE_get0(i); BIO_printf(bio_err, "\t%-10s\t%s\n", X509_PURPOSE_get0_sname(ptmp), X509_PURPOSE_get0_name(ptmp)); } } end: if (vpm) X509_VERIFY_PARAM_free(vpm); if (cert_ctx != NULL) X509_STORE_free(cert_ctx); sk_X509_pop_free(untrusted, X509_free); sk_X509_pop_free(trusted, X509_free); sk_X509_CRL_pop_free(crls, X509_CRL_free); release_engine(e); apps_shutdown(); OPENSSL_EXIT(ret < 0 ? 2 : ret); }
int checkCert(X509 *cert, char *CAfile, char *CApath) { X509_STORE *cert_ctx = NULL; int i; #if 0 /* FUTURE EXPANSION OF CAPABILITIES 1 */ int purpose = -1; char *untfile = NULL; char *trustfile = NULL; STACK_OF(X509) *untrusted = NULL; STACK_OF(X509) *trusted = NULL; #endif X509_LOOKUP *lookup = NULL; cert_ctx = X509_STORE_new(); if (cert_ctx == NULL) goto end; lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_file()); if (lookup == NULL) return 123456; if (CAfile) { i = X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM); if (!i) { fprintf(stderr, "Error loading file %s\n", CAfile); goto end; } } else { X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); } lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_hash_dir()); if (lookup == NULL) return 123456; if (CApath) { i = X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM); if (!i) { fprintf(stderr, "Error loading directory %s\n", CApath); goto end; } } else X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); #if 0 /* FUTURE EXPANSION OF CAPABILITIES 1 */ if (untfile) { if (!(untrusted = load_untrusted(untfile))) { fprintf(stderr, "Error loading untrusted file %s\n", untfile); goto end; } } if (trustfile) { if (!(trusted = load_untrusted(trustfile))) { fprintf(stderr, "Error loading untrusted file %s\n", trustfile); goto end; } } check(cert_ctx, cert, untrusted, trusted, purpose); #endif end: if (cert_ctx != NULL) X509_STORE_free(cert_ctx); #if 0 /* FUTURE EXPANSION OF CAPABILITIES 1 */ sk_X509_pop_free(untrusted, X509_free); sk_X509_pop_free(trusted, X509_free); #endif return 0; }
/* Creates a socket and listens on port 'port'. * Returns 1 on failure * Returns 0 on success. */ int mqtt3_socket_listen(struct _mqtt3_listener *listener) { int sock = -1; struct addrinfo hints; struct addrinfo *ainfo, *rp; char service[10]; int opt = 1; #ifndef WIN32 int ss_opt = 1; #else char ss_opt = 1; #endif #ifdef WITH_TLS int rc; X509_STORE *store; X509_LOOKUP *lookup; #endif char err[256]; if(!listener) return MOSQ_ERR_INVAL; snprintf(service, 10, "%d", listener->port); memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = PF_UNSPEC; hints.ai_flags = AI_PASSIVE; hints.ai_socktype = SOCK_STREAM; if(getaddrinfo(listener->host, service, &hints, &ainfo)) return INVALID_SOCKET; listener->sock_count = 0; listener->socks = NULL; for(rp = ainfo; rp; rp = rp->ai_next){ if(rp->ai_family == AF_INET){ _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Opening ipv4 listen socket on port %d.", ntohs(((struct sockaddr_in *)rp->ai_addr)->sin_port)); }else if(rp->ai_family == AF_INET6){ _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Opening ipv6 listen socket on port %d.", ntohs(((struct sockaddr_in6 *)rp->ai_addr)->sin6_port)); }else{ continue; } sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if(sock == -1){ strerror_r(errno, err, 256); _mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: %s", err); continue; } listener->sock_count++; listener->socks = _mosquitto_realloc(listener->socks, sizeof(int)*listener->sock_count); if(!listener->socks){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return MOSQ_ERR_NOMEM; } listener->socks[listener->sock_count-1] = sock; #ifndef WIN32 ss_opt = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &ss_opt, sizeof(ss_opt)); #endif ss_opt = 1; setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &ss_opt, sizeof(ss_opt)); #ifndef WIN32 /* Set non-blocking */ opt = fcntl(sock, F_GETFL, 0); if(opt == -1 || fcntl(sock, F_SETFL, opt | O_NONBLOCK) == -1){ /* If either fcntl fails, don't want to allow this client to connect. */ COMPAT_CLOSE(sock); return 1; } #else if(ioctlsocket(sock, FIONBIO, &opt)){ COMPAT_CLOSE(sock); return 1; } #endif if(bind(sock, rp->ai_addr, rp->ai_addrlen) == -1){ strerror_r(errno, err, 256); _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: %s", err); COMPAT_CLOSE(sock); return 1; } if(listen(sock, 100) == -1){ strerror_r(errno, err, 256); _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: %s", err); COMPAT_CLOSE(sock); return 1; } } freeaddrinfo(ainfo); /* We need to have at least one working socket. */ if(listener->sock_count > 0){ #ifdef WITH_TLS if((listener->cafile || listener->capath) && listener->certfile && listener->keyfile){ listener->ssl_ctx = SSL_CTX_new(TLSv1_server_method()); if(!listener->ssl_ctx){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Unable to create TLS context."); COMPAT_CLOSE(sock); return 1; } if(listener->ciphers){ rc = SSL_CTX_set_cipher_list(listener->ssl_ctx, listener->ciphers); if(rc == 0){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Unable to set TLS ciphers. Check cipher list \"%s\".", listener->ciphers); COMPAT_CLOSE(sock); return 1; } } rc = SSL_CTX_load_verify_locations(listener->ssl_ctx, listener->cafile, listener->capath); if(rc == 0){ if(listener->cafile && listener->capath){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Unable to load CA certificates. Check cafile \"%s\" and capath \"%s\".", listener->cafile, listener->capath); }else if(listener->cafile){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Unable to load CA certificates. Check cafile \"%s\".", listener->cafile); }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Unable to load CA certificates. Check capath \"%s\".", listener->capath); } COMPAT_CLOSE(sock); return 1; } /* FIXME user data? */ if(listener->require_certificate){ SSL_CTX_set_verify(listener->ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, client_certificate_verify); }else{ SSL_CTX_set_verify(listener->ssl_ctx, SSL_VERIFY_PEER, client_certificate_verify); } rc = SSL_CTX_use_certificate_file(listener->ssl_ctx, listener->certfile, SSL_FILETYPE_PEM); if(rc != 1){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Unable to load server certificate \"%s\". Check certfile.", listener->certfile); COMPAT_CLOSE(sock); return 1; } rc = SSL_CTX_use_PrivateKey_file(listener->ssl_ctx, listener->keyfile, SSL_FILETYPE_PEM); if(rc != 1){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Unable to load server key file \"%s\". Check keyfile.", listener->keyfile); COMPAT_CLOSE(sock); return 1; } rc = SSL_CTX_check_private_key(listener->ssl_ctx); if(rc != 1){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Server certificate/key are inconsistent."); COMPAT_CLOSE(sock); return 1; } /* Load CRLs if they exist. */ if(listener->crlfile){ store = SSL_CTX_get_cert_store(listener->ssl_ctx); if(!store){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Unable to obtain TLS store."); COMPAT_CLOSE(sock); return 1; } lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); rc = X509_load_crl_file(lookup, listener->crlfile, X509_FILETYPE_PEM); if(rc != 1){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Unable to load certificate revocation file \"%s\". Check crlfile.", listener->crlfile); COMPAT_CLOSE(sock); return 1; } X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK); } # ifdef WITH_TLS_PSK }else if(listener->psk_hint){ if(tls_ex_index_context == -1){ tls_ex_index_context = SSL_get_ex_new_index(0, "client context", NULL, NULL, NULL); } if(tls_ex_index_listener == -1){ tls_ex_index_listener = SSL_get_ex_new_index(0, "listener", NULL, NULL, NULL); } listener->ssl_ctx = SSL_CTX_new(TLSv1_server_method()); if(!listener->ssl_ctx){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Unable to create TLS context."); COMPAT_CLOSE(sock); return 1; } SSL_CTX_set_psk_server_callback(listener->ssl_ctx, psk_server_callback); if(listener->psk_hint){ rc = SSL_CTX_use_psk_identity_hint(listener->ssl_ctx, listener->psk_hint); if(rc == 0){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Unable to set TLS PSK hint."); COMPAT_CLOSE(sock); return 1; } } if(listener->ciphers){ rc = SSL_CTX_set_cipher_list(listener->ssl_ctx, listener->ciphers); if(rc == 0){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Unable to set TLS ciphers. Check cipher list \"%s\".", listener->ciphers); COMPAT_CLOSE(sock); return 1; } } # endif /* WITH_TLS_PSK */ } #endif /* WITH_TLS */ return 0; }else{ return 1; } }
X509_STORE* SSLContextManager::_getNewX509Store(const String& storePath) { PEG_METHOD_ENTER(TRC_SSL, "SSLContextManager::_getNewX509Store()"); // // reload certificates from the specified store // PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL2, "Reloading certificates from the store: " + storePath); X509_STORE* newStore = X509_STORE_new(); // // Check if there is a CA certificate file or directory specified. // If specified, load the certificates from the specified store path. // if (FileSystem::isDirectory(storePath)) { X509_LOOKUP* storeLookup = X509_STORE_add_lookup(newStore, X509_LOOKUP_hash_dir()); if (storeLookup == NULL) { X509_STORE_free(newStore); PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, "Could not reload the trust or crl store."); MessageLoaderParms parms( "Pegasus.Common.SSLContextManager.COULD_NOT_RELOAD_TRUST_OR_CRL_STORE", "Could not reload the trust or crl store."); PEG_METHOD_EXIT(); throw SSLException(parms); } X509_LOOKUP_add_dir(storeLookup, storePath.getCString(), X509_FILETYPE_PEM); } else if (FileSystem::exists(storePath)) { X509_LOOKUP* storeLookup = X509_STORE_add_lookup(newStore, X509_LOOKUP_file()); if (storeLookup == NULL) { X509_STORE_free(newStore); PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, "Could not reload the trust or crl store."); MessageLoaderParms parms( "Pegasus.Common.SSLContextManager.COULD_NOT_RELOAD_TRUST_OR_CRL_STORE", "Could not reload the trust or crl store."); PEG_METHOD_EXIT(); throw SSLException(parms); } X509_LOOKUP_load_file(storeLookup, storePath.getCString(), X509_FILETYPE_PEM); } else { PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, "Could not reload the trust or crl store, configured store not found."); MessageLoaderParms parms( "Pegasus.Common.SSLContextManager.CONFIGURED_TRUST_OR_CRL_STORE_NOT_FOUND", "Could not reload the trust or crl store, configured store not found."); PEG_METHOD_EXIT(); throw SSLException(parms); } PEG_METHOD_EXIT(); return newStore; }
int crl_main(int argc, char **argv) { unsigned long nmflag = 0; X509_CRL *x = NULL; int ret = 1, i; BIO *out = NULL; X509_STORE *store = NULL; X509_STORE_CTX ctx; X509_LOOKUP *lookup = NULL; X509_OBJECT xobj; EVP_PKEY *pkey; const EVP_MD *digest; char *digest_name = NULL; if (single_execution) { if (pledge("stdio cpath wpath rpath", NULL) == -1) { perror("pledge"); exit(1); } } if (bio_out == NULL) { if ((bio_out = BIO_new(BIO_s_file())) != NULL) { BIO_set_fp(bio_out, stdout, BIO_NOCLOSE); } } digest = EVP_sha1(); memset(&crl_config, 0, sizeof(crl_config)); crl_config.informat = FORMAT_PEM; crl_config.outformat = FORMAT_PEM; if (options_parse(argc, argv, crl_options, &digest_name, NULL) != 0) { crl_usage(); goto end; } if (crl_config.cafile != NULL || crl_config.capath != NULL) crl_config.verify = 1; if (crl_config.nameopt != NULL) { if (set_name_ex(&nmflag, crl_config.nameopt) != 1) { fprintf(stderr, "Invalid -nameopt argument '%s'\n", crl_config.nameopt); goto end; } } if (digest_name != NULL) { if ((digest = EVP_get_digestbyname(digest_name)) == NULL) { fprintf(stderr, "Unknown message digest algorithm '%s'\n", digest_name); goto end; } } x = load_crl(crl_config.infile, crl_config.informat); if (x == NULL) goto end; if (crl_config.verify) { store = X509_STORE_new(); lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); if (lookup == NULL) goto end; if (!X509_LOOKUP_load_file(lookup, crl_config.cafile, X509_FILETYPE_PEM)) X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); if (lookup == NULL) goto end; if (!X509_LOOKUP_add_dir(lookup, crl_config.capath, X509_FILETYPE_PEM)) X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); ERR_clear_error(); if (!X509_STORE_CTX_init(&ctx, store, NULL, NULL)) { BIO_printf(bio_err, "Error initialising X509 store\n"); goto end; } i = X509_STORE_get_by_subject(&ctx, X509_LU_X509, X509_CRL_get_issuer(x), &xobj); if (i <= 0) { BIO_printf(bio_err, "Error getting CRL issuer certificate\n"); goto end; } pkey = X509_get_pubkey(xobj.data.x509); X509_OBJECT_free_contents(&xobj); if (!pkey) { BIO_printf(bio_err, "Error getting CRL issuer public key\n"); goto end; } i = X509_CRL_verify(x, pkey); EVP_PKEY_free(pkey); if (i < 0) goto end; if (i == 0) BIO_printf(bio_err, "verify failure\n"); else BIO_printf(bio_err, "verify OK\n"); } /* Print requested information the order that the flags were given. */ for (i = 1; i <= argc; i++) { if (crl_config.issuer == i) { print_name(bio_out, "issuer=", X509_CRL_get_issuer(x), nmflag); } if (crl_config.crlnumber == i) { ASN1_INTEGER *crlnum; crlnum = X509_CRL_get_ext_d2i(x, NID_crl_number, NULL, NULL); BIO_printf(bio_out, "crlNumber="); if (crlnum) { i2a_ASN1_INTEGER(bio_out, crlnum); ASN1_INTEGER_free(crlnum); } else BIO_puts(bio_out, "<NONE>"); BIO_printf(bio_out, "\n"); } if (crl_config.hash == i) { BIO_printf(bio_out, "%08lx\n", X509_NAME_hash(X509_CRL_get_issuer(x))); } #ifndef OPENSSL_NO_MD5 if (crl_config.hash_old == i) { BIO_printf(bio_out, "%08lx\n", X509_NAME_hash_old(X509_CRL_get_issuer(x))); } #endif if (crl_config.lastupdate == i) { BIO_printf(bio_out, "lastUpdate="); ASN1_TIME_print(bio_out, X509_CRL_get_lastUpdate(x)); BIO_printf(bio_out, "\n"); } if (crl_config.nextupdate == i) { BIO_printf(bio_out, "nextUpdate="); if (X509_CRL_get_nextUpdate(x)) ASN1_TIME_print(bio_out, X509_CRL_get_nextUpdate(x)); else BIO_printf(bio_out, "NONE"); BIO_printf(bio_out, "\n"); } if (crl_config.fingerprint == i) { int j; unsigned int n; unsigned char md[EVP_MAX_MD_SIZE]; if (!X509_CRL_digest(x, digest, md, &n)) { BIO_printf(bio_err, "out of memory\n"); goto end; } BIO_printf(bio_out, "%s Fingerprint=", OBJ_nid2sn(EVP_MD_type(digest))); for (j = 0; j < (int) n; j++) { BIO_printf(bio_out, "%02X%c", md[j], (j + 1 == (int)n) ? '\n' : ':'); } } } out = BIO_new(BIO_s_file()); if (out == NULL) { ERR_print_errors(bio_err); goto end; } if (crl_config.outfile == NULL) { BIO_set_fp(out, stdout, BIO_NOCLOSE); } else { if (BIO_write_filename(out, crl_config.outfile) <= 0) { perror(crl_config.outfile); goto end; } } if (crl_config.text) X509_CRL_print(out, x); if (crl_config.noout) { ret = 0; goto end; } if (crl_config.outformat == FORMAT_ASN1) i = (int) i2d_X509_CRL_bio(out, x); else if (crl_config.outformat == FORMAT_PEM) i = PEM_write_bio_X509_CRL(out, x); else { BIO_printf(bio_err, "bad output format specified for outfile\n"); goto end; } if (!i) { BIO_printf(bio_err, "unable to write CRL\n"); goto end; } ret = 0; end: BIO_free_all(out); BIO_free_all(bio_out); bio_out = NULL; X509_CRL_free(x); if (store) { X509_STORE_CTX_cleanup(&ctx); X509_STORE_free(store); } return (ret); }
int MAIN(int argc, char **argv) { unsigned long nmflag = 0; X509_CRL *x=NULL; char *CAfile = NULL, *CApath = NULL; int ret=1,i,num,badops=0; BIO *out=NULL; int informat,outformat; char *infile=NULL,*outfile=NULL; int hash=0,issuer=0,lastupdate=0,nextupdate=0,noout=0,text=0; int fingerprint = 0, crlnumber = 0; const char **pp; X509_STORE *store = NULL; X509_STORE_CTX ctx; X509_LOOKUP *lookup = NULL; X509_OBJECT xobj; EVP_PKEY *pkey; int do_ver = 0; const EVP_MD *md_alg,*digest=EVP_sha1(); apps_startup(); if (bio_err == NULL) if ((bio_err=BIO_new(BIO_s_file())) != NULL) BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); if (!load_config(bio_err, NULL)) goto end; if (bio_out == NULL) if ((bio_out=BIO_new(BIO_s_file())) != NULL) { BIO_set_fp(bio_out,stdout,BIO_NOCLOSE); #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); bio_out = BIO_push(tmpbio, bio_out); } #endif } informat=FORMAT_PEM; outformat=FORMAT_PEM; argc--; argv++; num=0; while (argc >= 1) { #ifdef undef if (strcmp(*argv,"-p") == 0) { if (--argc < 1) goto bad; if (!args_from_file(++argv,Nargc,Nargv)) { goto end; }*/ } #endif if (strcmp(*argv,"-inform") == 0) { if (--argc < 1) goto bad; informat=str2fmt(*(++argv)); } else if (strcmp(*argv,"-outform") == 0) { if (--argc < 1) goto bad; outformat=str2fmt(*(++argv)); } else if (strcmp(*argv,"-in") == 0) { if (--argc < 1) goto bad; infile= *(++argv); } else if (strcmp(*argv,"-out") == 0) { if (--argc < 1) goto bad; outfile= *(++argv); } else if (strcmp(*argv,"-CApath") == 0) { if (--argc < 1) goto bad; CApath = *(++argv); do_ver = 1; } else if (strcmp(*argv,"-CAfile") == 0) { if (--argc < 1) goto bad; CAfile = *(++argv); do_ver = 1; } else if (strcmp(*argv,"-verify") == 0) do_ver = 1; else if (strcmp(*argv,"-text") == 0) text = 1; else if (strcmp(*argv,"-hash") == 0) hash= ++num; else if (strcmp(*argv,"-nameopt") == 0) { if (--argc < 1) goto bad; if (!set_name_ex(&nmflag, *(++argv))) goto bad; } else if (strcmp(*argv,"-issuer") == 0) issuer= ++num; else if (strcmp(*argv,"-lastupdate") == 0) lastupdate= ++num; else if (strcmp(*argv,"-nextupdate") == 0) nextupdate= ++num; else if (strcmp(*argv,"-noout") == 0) noout= ++num; else if (strcmp(*argv,"-fingerprint") == 0) fingerprint= ++num; else if (strcmp(*argv,"-crlnumber") == 0) crlnumber= ++num; else if ((md_alg=EVP_get_digestbyname(*argv + 1))) { /* ok */ digest=md_alg; } else { BIO_printf(bio_err,"unknown option %s\n",*argv); badops=1; break; } argc--; argv++; } if (badops) { bad: for (pp=crl_usage; (*pp != NULL); pp++) BIO_printf(bio_err,"%s",*pp); goto end; } ERR_load_crypto_strings(); x=load_crl(infile,informat); if (x == NULL) { goto end; } if(do_ver) { store = X509_STORE_new(); lookup=X509_STORE_add_lookup(store,X509_LOOKUP_file()); if (lookup == NULL) goto end; if (!X509_LOOKUP_load_file(lookup,CAfile,X509_FILETYPE_PEM)) X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT); lookup=X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir()); if (lookup == NULL) goto end; if (!X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM)) X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT); ERR_clear_error(); if(!X509_STORE_CTX_init(&ctx, store, NULL, NULL)) { BIO_printf(bio_err, "Error initialising X509 store\n"); goto end; } i = X509_STORE_get_by_subject(&ctx, X509_LU_X509, X509_CRL_get_issuer(x), &xobj); if(i <= 0) { BIO_printf(bio_err, "Error getting CRL issuer certificate\n"); goto end; } pkey = X509_get_pubkey(xobj.data.x509); X509_OBJECT_free_contents(&xobj); if(!pkey) { BIO_printf(bio_err, "Error getting CRL issuer public key\n"); goto end; } i = X509_CRL_verify(x, pkey); EVP_PKEY_free(pkey); if(i < 0) goto end; if(i == 0) BIO_printf(bio_err, "verify failure\n"); else BIO_printf(bio_err, "verify OK\n"); } if (num) { for (i=1; i<=num; i++) { if (issuer == i) { print_name(bio_out, "issuer=", X509_CRL_get_issuer(x), nmflag); } if (crlnumber == i) { ASN1_INTEGER *crlnum; crlnum = X509_CRL_get_ext_d2i(x, NID_crl_number, NULL, NULL); BIO_printf(bio_out,"crlNumber="); if (crlnum) { i2a_ASN1_INTEGER(bio_out, crlnum); ASN1_INTEGER_free(crlnum); } else BIO_puts(bio_out, "<NONE>"); BIO_printf(bio_out,"\n"); } if (hash == i) { BIO_printf(bio_out,"%08lx\n", X509_NAME_hash(X509_CRL_get_issuer(x))); } if (lastupdate == i) { BIO_printf(bio_out,"lastUpdate="); ASN1_TIME_print(bio_out, X509_CRL_get_lastUpdate(x)); BIO_printf(bio_out,"\n"); } if (nextupdate == i) { BIO_printf(bio_out,"nextUpdate="); if (X509_CRL_get_nextUpdate(x)) ASN1_TIME_print(bio_out, X509_CRL_get_nextUpdate(x)); else BIO_printf(bio_out,"NONE"); BIO_printf(bio_out,"\n"); } if (fingerprint == i) { int j; unsigned int n; unsigned char md[EVP_MAX_MD_SIZE]; if (!X509_CRL_digest(x,digest,md,&n)) { BIO_printf(bio_err,"out of memory\n"); goto end; } BIO_printf(bio_out,"%s Fingerprint=", OBJ_nid2sn(EVP_MD_type(digest))); for (j=0; j<(int)n; j++) { BIO_printf(bio_out,"%02X%c",md[j], (j+1 == (int)n) ?'\n':':'); } } } } out=BIO_new(BIO_s_file()); if (out == NULL) { ERR_print_errors(bio_err); goto end; } if (outfile == NULL) { BIO_set_fp(out,stdout,BIO_NOCLOSE); #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); out = BIO_push(tmpbio, out); } #endif } else { if (BIO_write_filename(out,outfile) <= 0) { perror(outfile); goto end; } } if (text) X509_CRL_print(out, x); if (noout) { ret = 0; goto end; } if (outformat == FORMAT_ASN1) i=(int)i2d_X509_CRL_bio(out,x); else if (outformat == FORMAT_PEM) i=PEM_write_bio_X509_CRL(out,x); else { BIO_printf(bio_err,"bad output format specified for outfile\n"); goto end; } if (!i) { BIO_printf(bio_err,"unable to write CRL\n"); goto end; } ret=0; end: BIO_free_all(out); BIO_free_all(bio_out); bio_out=NULL; X509_CRL_free(x); if(store) { X509_STORE_CTX_cleanup(&ctx); X509_STORE_free(store); } apps_shutdown(); OPENSSL_EXIT(ret); }
void tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file, #if ENABLE_INLINE_FILES const char *ca_file_inline, #endif const char *ca_path, bool tls_server ) { int status; ASSERT(NULL != ctx); #if ENABLE_INLINE_FILES if (ca_file && !strcmp (ca_file, INLINE_FILE_TAG) && ca_file_inline) { status = use_inline_load_verify_locations (ctx->ctx, ca_file_inline); } else #endif { /* Load CA file for verifying peer supplied certificate */ status = SSL_CTX_load_verify_locations (ctx->ctx, ca_file, ca_path); } if (!status) msg (M_SSLERR, "Cannot load CA certificate file %s path %s (SSL_CTX_load_verify_locations)", np(ca_file), np(ca_path)); /* Set a store for certs (CA & CRL) with a lookup on the "capath" hash directory */ if (ca_path) { X509_STORE *store = SSL_CTX_get_cert_store(ctx->ctx); if (store) { X509_LOOKUP *lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); if (!X509_LOOKUP_add_dir(lookup, ca_path, X509_FILETYPE_PEM)) X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); else msg(M_WARN, "WARNING: experimental option --capath %s", ca_path); #if OPENSSL_VERSION_NUMBER >= 0x00907000L X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); #else msg(M_WARN, "WARNING: this version of OpenSSL cannot handle CRL files in capath"); #endif } else msg(M_SSLERR, "Cannot get certificate store (SSL_CTX_get_cert_store)"); } /* Load names of CAs from file and use it as a client CA list */ if (ca_file && tls_server) { STACK_OF(X509_NAME) *cert_names = NULL; #if ENABLE_INLINE_FILES if (!strcmp (ca_file, INLINE_FILE_TAG) && ca_file_inline) { cert_names = use_inline_load_client_CA_file (ctx->ctx, ca_file_inline); } else #endif { cert_names = SSL_load_client_CA_file (ca_file); } if (!cert_names) msg (M_SSLERR, "Cannot load CA certificate file %s (SSL_load_client_CA_file)", ca_file); SSL_CTX_set_client_CA_list (ctx->ctx, cert_names); } }
int crl_main(int argc, char **argv) { X509_CRL *x = NULL; BIO *out = NULL; X509_STORE *store = NULL; X509_STORE_CTX *ctx = NULL; X509_LOOKUP *lookup = NULL; X509_OBJECT *xobj = NULL; EVP_PKEY *pkey; const EVP_MD *digest = EVP_sha1(); unsigned long nmflag = 0; char nmflag_set = 0; char *infile = NULL, *outfile = NULL, *crldiff = NULL, *keyfile = NULL; const char *CAfile = NULL, *CApath = NULL, *prog; OPTION_CHOICE o; int hash = 0, issuer = 0, lastupdate = 0, nextupdate = 0, noout = 0; int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM; int ret = 1, num = 0, badsig = 0, fingerprint = 0, crlnumber = 0; int text = 0, do_ver = 0, noCAfile = 0, noCApath = 0; int i; #ifndef OPENSSL_NO_MD5 int hash_old = 0; #endif prog = opt_init(argc, argv, crl_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { case OPT_EOF: case OPT_ERR: opthelp: BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); goto end; case OPT_HELP: opt_help(crl_options); ret = 0; goto end; case OPT_INFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) goto opthelp; break; case OPT_IN: infile = opt_arg(); break; case OPT_OUTFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) goto opthelp; break; case OPT_OUT: outfile = opt_arg(); break; case OPT_KEYFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat)) goto opthelp; break; case OPT_KEY: keyfile = opt_arg(); break; case OPT_GENDELTA: crldiff = opt_arg(); break; case OPT_CAPATH: CApath = opt_arg(); do_ver = 1; break; case OPT_CAFILE: CAfile = opt_arg(); do_ver = 1; break; case OPT_NOCAPATH: noCApath = 1; break; case OPT_NOCAFILE: noCAfile = 1; break; case OPT_HASH_OLD: #ifndef OPENSSL_NO_MD5 hash_old = ++num; #endif break; case OPT_VERIFY: do_ver = 1; break; case OPT_TEXT: text = 1; break; case OPT_HASH: hash = ++num; break; case OPT_ISSUER: issuer = ++num; break; case OPT_LASTUPDATE: lastupdate = ++num; break; case OPT_NEXTUPDATE: nextupdate = ++num; break; case OPT_NOOUT: noout = ++num; break; case OPT_FINGERPRINT: fingerprint = ++num; break; case OPT_CRLNUMBER: crlnumber = ++num; break; case OPT_BADSIG: badsig = 1; break; case OPT_NAMEOPT: nmflag_set = 1; if (!set_name_ex(&nmflag, opt_arg())) goto opthelp; break; case OPT_MD: if (!opt_md(opt_unknown(), &digest)) goto opthelp; } } argc = opt_num_rest(); if (argc != 0) goto opthelp; if (!nmflag_set) nmflag = XN_FLAG_ONELINE; x = load_crl(infile, informat); if (x == NULL) goto end; if (do_ver) { if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL) goto end; lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); if (lookup == NULL) goto end; ctx = X509_STORE_CTX_new(); if (ctx == NULL || !X509_STORE_CTX_init(ctx, store, NULL, NULL)) { BIO_printf(bio_err, "Error initialising X509 store\n"); goto end; } xobj = X509_STORE_CTX_get_obj_by_subject(ctx, X509_LU_X509, X509_CRL_get_issuer(x)); if (xobj == NULL) { BIO_printf(bio_err, "Error getting CRL issuer certificate\n"); goto end; } pkey = X509_get_pubkey(X509_OBJECT_get0_X509(xobj)); X509_OBJECT_free(xobj); if (!pkey) { BIO_printf(bio_err, "Error getting CRL issuer public key\n"); goto end; } i = X509_CRL_verify(x, pkey); EVP_PKEY_free(pkey); if (i < 0) goto end; if (i == 0) BIO_printf(bio_err, "verify failure\n"); else BIO_printf(bio_err, "verify OK\n"); } if (crldiff) { X509_CRL *newcrl, *delta; if (!keyfile) { BIO_puts(bio_err, "Missing CRL signing key\n"); goto end; } newcrl = load_crl(crldiff, informat); if (!newcrl) goto end; pkey = load_key(keyfile, keyformat, 0, NULL, NULL, "CRL signing key"); if (!pkey) { X509_CRL_free(newcrl); goto end; } delta = X509_CRL_diff(x, newcrl, pkey, digest, 0); X509_CRL_free(newcrl); EVP_PKEY_free(pkey); if (delta) { X509_CRL_free(x); x = delta; } else { BIO_puts(bio_err, "Error creating delta CRL\n"); goto end; } } if (badsig) { const ASN1_BIT_STRING *sig; X509_CRL_get0_signature(x, &sig, NULL); corrupt_signature(sig); } if (num) { for (i = 1; i <= num; i++) { if (issuer == i) { print_name(bio_out, "issuer=", X509_CRL_get_issuer(x), nmflag); } if (crlnumber == i) { ASN1_INTEGER *crlnum; crlnum = X509_CRL_get_ext_d2i(x, NID_crl_number, NULL, NULL); BIO_printf(bio_out, "crlNumber="); if (crlnum) { i2a_ASN1_INTEGER(bio_out, crlnum); ASN1_INTEGER_free(crlnum); } else BIO_puts(bio_out, "<NONE>"); BIO_printf(bio_out, "\n"); } if (hash == i) { BIO_printf(bio_out, "%08lx\n", X509_NAME_hash(X509_CRL_get_issuer(x))); } #ifndef OPENSSL_NO_MD5 if (hash_old == i) { BIO_printf(bio_out, "%08lx\n", X509_NAME_hash_old(X509_CRL_get_issuer(x))); } #endif if (lastupdate == i) { BIO_printf(bio_out, "lastUpdate="); ASN1_TIME_print(bio_out, X509_CRL_get0_lastUpdate(x)); BIO_printf(bio_out, "\n"); } if (nextupdate == i) { BIO_printf(bio_out, "nextUpdate="); if (X509_CRL_get0_nextUpdate(x)) ASN1_TIME_print(bio_out, X509_CRL_get0_nextUpdate(x)); else BIO_printf(bio_out, "NONE"); BIO_printf(bio_out, "\n"); } if (fingerprint == i) { int j; unsigned int n; unsigned char md[EVP_MAX_MD_SIZE]; if (!X509_CRL_digest(x, digest, md, &n)) { BIO_printf(bio_err, "out of memory\n"); goto end; } BIO_printf(bio_out, "%s Fingerprint=", OBJ_nid2sn(EVP_MD_type(digest))); for (j = 0; j < (int)n; j++) { BIO_printf(bio_out, "%02X%c", md[j], (j + 1 == (int)n) ? '\n' : ':'); } } } } out = bio_open_default(outfile, 'w', outformat); if (out == NULL) goto end; if (text) X509_CRL_print(out, x); if (noout) { ret = 0; goto end; } if (outformat == FORMAT_ASN1) i = (int)i2d_X509_CRL_bio(out, x); else i = PEM_write_bio_X509_CRL(out, x); if (!i) { BIO_printf(bio_err, "unable to write CRL\n"); goto end; } ret = 0; end: if (ret != 0) ERR_print_errors(bio_err); BIO_free_all(out); X509_CRL_free(x); X509_STORE_CTX_free(ctx); X509_STORE_free(store); return (ret); }
int verify_main(int argc, char **argv) { int i, ret = 1, badarg = 0; char *CApath = NULL, *CAfile = NULL; char *untfile = NULL, *trustfile = NULL, *crlfile = NULL; STACK_OF(X509) * untrusted = NULL, *trusted = NULL; STACK_OF(X509_CRL) * crls = NULL; X509_STORE *cert_ctx = NULL; X509_LOOKUP *lookup = NULL; X509_VERIFY_PARAM *vpm = NULL; if (single_execution) { if (pledge("stdio rpath", NULL) == -1) { perror("pledge"); exit(1); } } cert_ctx = X509_STORE_new(); if (cert_ctx == NULL) goto end; X509_STORE_set_verify_cb(cert_ctx, cb); argc--; argv++; for (;;) { if (argc >= 1) { if (strcmp(*argv, "-CApath") == 0) { if (argc-- < 1) goto end; CApath = *(++argv); } else if (strcmp(*argv, "-CAfile") == 0) { if (argc-- < 1) goto end; CAfile = *(++argv); } else if (args_verify(&argv, &argc, &badarg, bio_err, &vpm)) { if (badarg) goto end; continue; } else if (strcmp(*argv, "-untrusted") == 0) { if (argc-- < 1) goto end; untfile = *(++argv); } else if (strcmp(*argv, "-trusted") == 0) { if (argc-- < 1) goto end; trustfile = *(++argv); } else if (strcmp(*argv, "-CRLfile") == 0) { if (argc-- < 1) goto end; crlfile = *(++argv); } else if (strcmp(*argv, "-help") == 0) goto end; else if (strcmp(*argv, "-verbose") == 0) v_verbose = 1; else if (argv[0][0] == '-') goto end; else break; argc--; argv++; } else break; } if (vpm) X509_STORE_set1_param(cert_ctx, vpm); lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_file()); if (lookup == NULL) abort(); if (CAfile) { i = X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM); if (!i) { BIO_printf(bio_err, "Error loading file %s\n", CAfile); ERR_print_errors(bio_err); goto end; } } else X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_hash_dir()); if (lookup == NULL) abort(); if (CApath) { i = X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM); if (!i) { BIO_printf(bio_err, "Error loading directory %s\n", CApath); ERR_print_errors(bio_err); goto end; } } else X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); ERR_clear_error(); if (untfile) { untrusted = load_certs(bio_err, untfile, FORMAT_PEM, NULL, "untrusted certificates"); if (!untrusted) goto end; } if (trustfile) { trusted = load_certs(bio_err, trustfile, FORMAT_PEM, NULL, "trusted certificates"); if (!trusted) goto end; } if (crlfile) { crls = load_crls(bio_err, crlfile, FORMAT_PEM, NULL, "other CRLs"); if (!crls) goto end; } ret = 0; if (argc < 1) { if (1 != check(cert_ctx, NULL, untrusted, trusted, crls)) ret = -1; } else { for (i = 0; i < argc; i++) if (1 != check(cert_ctx, argv[i], untrusted, trusted, crls)) ret = -1; } end: if (ret == 1) { BIO_printf(bio_err, "usage: verify [-verbose] [-CApath path] [-CAfile file] [-purpose purpose] [-crl_check]"); BIO_printf(bio_err, " [-attime timestamp]"); BIO_printf(bio_err, " cert1 cert2 ...\n"); BIO_printf(bio_err, "recognized usages:\n"); for (i = 0; i < X509_PURPOSE_get_count(); i++) { X509_PURPOSE *ptmp; ptmp = X509_PURPOSE_get0(i); BIO_printf(bio_err, "\t%-10s\t%s\n", X509_PURPOSE_get0_sname(ptmp), X509_PURPOSE_get0_name(ptmp)); } } if (vpm) X509_VERIFY_PARAM_free(vpm); if (cert_ctx != NULL) X509_STORE_free(cert_ctx); sk_X509_pop_free(untrusted, X509_free); sk_X509_pop_free(trusted, X509_free); sk_X509_CRL_pop_free(crls, X509_CRL_free); return (ret < 0 ? 2 : ret); }
int check_validity_of_cert( const char *cFile, const unsigned char *md5_md, unsigned char *sfileMsg, const int sfsize, const char* caPath ) { int retval = 0; X509 *cert; X509_STORE *store; X509_LOOKUP *lookup; X509_STORE_CTX *ctx = 0; EVP_PKEY *pubKey; BIO *bio; bio = BIO_new(BIO_s_file()); BIO_read_filename(bio, cFile); if (NULL == (cert = PEM_read_bio_X509(bio, NULL, 0, NULL))) { BIO_vfree(bio); return 0; } // verify certificate store = X509_STORE_new(); lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); X509_LOOKUP_add_dir(lookup, (char *)caPath, X509_FILETYPE_PEM); if ((ctx = X509_STORE_CTX_new()) != 0) { if (X509_STORE_CTX_init(ctx, store, cert, 0) == 1) retval = X509_verify_cert(ctx); X509_STORE_CTX_free(ctx); } X509_STORE_free(store); if (retval != 1) { fprintf(stderr,"ERROR: Cannot verify certificate ('%s')\n", cFile); return 0; } pubKey = X509_get_pubkey(cert); if (!pubKey) { X509_free(cert); BIO_vfree(bio); return 0; } if (pubKey->type == EVP_PKEY_RSA) { BN_CTX *c = BN_CTX_new(); if (!c) { X509_free(cert); EVP_PKEY_free(pubKey); BIO_vfree(bio); return 0; } if (!RSA_blinding_on(pubKey->pkey.rsa, c)) { X509_free(cert); EVP_PKEY_free(pubKey); BIO_vfree(bio); BN_CTX_free(c); return 0; } retval = RSA_verify(NID_md5, md5_md, MD5_DIGEST_LENGTH, sfileMsg, sfsize, pubKey->pkey.rsa); RSA_blinding_off(pubKey->pkey.rsa); BN_CTX_free(c); } if (pubKey->type == EVP_PKEY_DSA) { fprintf(stderr, "ERROR: DSA keys are not supported.\n"); return 0; } EVP_PKEY_free(pubKey); X509_free(cert); BIO_vfree(bio); return retval; }
static int xmlSecOpenSSLX509StoreInitialize(xmlSecKeyDataStorePtr store) { const xmlChar* path; X509_LOOKUP *lookup = NULL; xmlSecOpenSSLX509StoreCtxPtr ctx; xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), -1); ctx = xmlSecOpenSSLX509StoreGetCtx(store); xmlSecAssert2(ctx != NULL, -1); memset(ctx, 0, sizeof(xmlSecOpenSSLX509StoreCtx)); ctx->xst = X509_STORE_new(); if(ctx->xst == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "X509_STORE_new", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } if(!X509_STORE_set_default_paths(ctx->xst)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "X509_STORE_set_default_paths", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } lookup = X509_STORE_add_lookup(ctx->xst, X509_LOOKUP_hash_dir()); if(lookup == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "X509_STORE_add_lookup", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } path = xmlSecOpenSSLGetDefaultTrustedCertsFolder(); if(path != NULL) { if(!X509_LOOKUP_add_dir(lookup, (char*)path, X509_FILETYPE_PEM)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "X509_LOOKUP_add_dir", XMLSEC_ERRORS_R_CRYPTO_FAILED, "path='%s'", xmlSecErrorsSafeString(path) ); return(-1); } } else { if(!X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT)) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "X509_LOOKUP_add_dir", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE ); return(-1); } } ctx->untrusted = sk_X509_new_null(); if(ctx->untrusted == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "sk_X509_new_null", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } ctx->crls = sk_X509_CRL_new_null(); if(ctx->crls == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "sk_X509_CRL_new_null", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } #if !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) ctx->vpm = X509_VERIFY_PARAM_new(); if(ctx->vpm == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "X509_VERIFY_PARAM_new", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } X509_VERIFY_PARAM_set_depth(ctx->vpm, 9); /* the default cert verification path in openssl */ X509_STORE_set1_param(ctx->xst, ctx->vpm); #else /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */ ctx->xst->depth = 9; /* the default cert verification path in openssl */ #endif /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */ return(0); }
bool ssl_init (void) { SSL_METHOD const *meth; long ssl_options = 0; #if OPENSSL_VERSION_NUMBER >= 0x00907000 if (ssl_true_initialized == 0) { OPENSSL_config (NULL); ssl_true_initialized = 1; } #endif if (ssl_ctx) /* The SSL has already been initialized. */ return true; /* Init the PRNG. If that fails, bail out. */ init_prng (); if (RAND_status () != 1) { logprintf (LOG_NOTQUIET, _("Could not seed PRNG; consider using --random-file.\n")); goto error; } #if OPENSSL_VERSION_NUMBER >= 0x00907000 OPENSSL_load_builtin_modules(); ENGINE_load_builtin_engines(); CONF_modules_load_file(NULL, NULL, CONF_MFLAGS_DEFAULT_SECTION|CONF_MFLAGS_IGNORE_MISSING_FILE); #endif SSL_library_init (); SSL_load_error_strings (); SSLeay_add_all_algorithms (); SSLeay_add_ssl_algorithms (); switch (opt.secure_protocol) { #ifndef OPENSSL_NO_SSL2 case secure_protocol_sslv2: meth = SSLv2_client_method (); break; #endif #ifndef OPENSSL_NO_SSL3 case secure_protocol_sslv3: meth = SSLv3_client_method (); break; #endif case secure_protocol_auto: case secure_protocol_pfs: meth = SSLv23_client_method (); ssl_options |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; break; case secure_protocol_tlsv1: meth = TLSv1_client_method (); break; #if OPENSSL_VERSION_NUMBER >= 0x10001000 case secure_protocol_tlsv1_1: meth = TLSv1_1_client_method (); break; case secure_protocol_tlsv1_2: meth = TLSv1_2_client_method (); break; #else case secure_protocol_tlsv1_1: logprintf (LOG_NOTQUIET, _("Your OpenSSL version is too old to support TLSv1.1\n")); goto error; case secure_protocol_tlsv1_2: logprintf (LOG_NOTQUIET, _("Your OpenSSL version is too old to support TLSv1.2\n")); goto error; #endif default: logprintf (LOG_NOTQUIET, _("OpenSSL: unimplemented 'secure-protocol' option value %d\n"), opt.secure_protocol); logprintf (LOG_NOTQUIET, _("Please report this issue to [email protected]\n")); abort (); } /* The type cast below accommodates older OpenSSL versions (0.9.8) where SSL_CTX_new() is declared without a "const" argument. */ ssl_ctx = SSL_CTX_new ((SSL_METHOD *)meth); if (!ssl_ctx) goto error; if (ssl_options) SSL_CTX_set_options (ssl_ctx, ssl_options); /* OpenSSL ciphers: https://www.openssl.org/docs/apps/ciphers.html * Since we want a good protection, we also use HIGH (that excludes MD4 ciphers and some more) */ if (opt.secure_protocol == secure_protocol_pfs) SSL_CTX_set_cipher_list (ssl_ctx, "HIGH:MEDIUM:!RC4:!SRP:!PSK:!RSA:!aNULL@STRENGTH"); SSL_CTX_set_default_verify_paths (ssl_ctx); SSL_CTX_load_verify_locations (ssl_ctx, opt.ca_cert, opt.ca_directory); if (opt.crl_file) { X509_STORE *store = SSL_CTX_get_cert_store (ssl_ctx); X509_LOOKUP *lookup; if (!(lookup = X509_STORE_add_lookup (store, X509_LOOKUP_file ())) || (!X509_load_crl_file (lookup, opt.crl_file, X509_FILETYPE_PEM))) goto error; X509_STORE_set_flags (store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); } /* SSL_VERIFY_NONE instructs OpenSSL not to abort SSL_connect if the certificate is invalid. We verify the certificate separately in ssl_check_certificate, which provides much better diagnostics than examining the error stack after a failed SSL_connect. */ SSL_CTX_set_verify (ssl_ctx, SSL_VERIFY_NONE, NULL); /* Use the private key from the cert file unless otherwise specified. */ if (opt.cert_file && !opt.private_key) { opt.private_key = opt.cert_file; opt.private_key_type = opt.cert_type; } if (opt.cert_file) if (SSL_CTX_use_certificate_file (ssl_ctx, opt.cert_file, key_type_to_ssl_type (opt.cert_type)) != 1) goto error; if (opt.private_key) if (SSL_CTX_use_PrivateKey_file (ssl_ctx, opt.private_key, key_type_to_ssl_type (opt.private_key_type)) != 1) goto error; /* Since fd_write unconditionally assumes partial writes (and handles them correctly), allow them in OpenSSL. */ SSL_CTX_set_mode (ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE); /* The OpenSSL library can handle renegotiations automatically, so tell it to do so. */ SSL_CTX_set_mode (ssl_ctx, SSL_MODE_AUTO_RETRY); return true; error: if (ssl_ctx) SSL_CTX_free (ssl_ctx); print_errors (); return false; }