esock_openssl.c
来自「OTP是开放电信平台的简称」· C语言 代码 · 共 1,212 行 · 第 1/3 页
C
1,212 行
* */int esock_ssl_connect(Connection *cp){ int ret, ssl_error; SSL *ssl = cp->opaque; RESET_ERRSTR(); DEBUGF(("esock_ssl_connect: calling SSL_connect fd = %d\n" " state before: %s\n", cp->fd, SSL_state_string(ssl))); ret = SSL_connect(ssl); ssl_error = SSL_get_error(ssl, ret); DEBUGF((" SSL_connect() = %d\n" " ssl_error: %s\n" " state after: %s\n", ret, ssl_error_str(ssl_error), SSL_state_string(ssl))); if (ret > 0) return ret; else if (ret == 0) { /* permanent connect error */ sock_set_errno(ERRNO_NONE); MAYBE_SET_ERRSTR("esslconnect"); return -1; } end_ssl_call(ret, cp, ssl_error); return ret;}int esock_ssl_session_reused(Connection *cp){ SSL *ssl = cp->opaque; return SSL_session_reused(ssl);}/* esock_ssl_read(Connection *cp, char *buf, int len) * * Read at most `len' chars into `buf'. Returns number of chars * read ( > 0), or 0 at EOF, or -1 on error. Sets cp->eof, cp->bp if * appropriate. */int esock_ssl_read(Connection *cp, char *buf, int len){ int ret, ssl_error; SSL *ssl = cp->opaque; RESET_ERRSTR(); DEBUGF(("esock_ssl_read: calling SSL_read fd = %d\n" " state before: %s\n", cp->fd, SSL_state_string(ssl))); ret = SSL_read(ssl, buf, len); ssl_error = SSL_get_error(ssl, ret); DEBUGF((" SSL_read = %d\n" " ssl_error: %s\n" " state after: %s\n", ret, ssl_error_str(ssl_error), SSL_state_string(ssl))); if (ssl_error == SSL_ERROR_NONE) { DEBUGMSGF(("message (hex) : [%3.*a]\n", ret, buf)); DEBUGMSGF(("message (char): [%3.*b]\n", ret, buf)); } if (ret > 0) return ret; if (ret == 0) { check_shutdown(cp); return ret; } end_ssl_call(ret, cp, ssl_error); return ret;}/* * esock_ssl_write(Connection *cp, char *buf, int len) * * Writes at most `len' chars from `buf'. Returns number of chars * written, or -1 on error. */int esock_ssl_write(Connection *cp, char *buf, int len){ int ret, ssl_error; SSL *ssl = cp->opaque; RESET_ERRSTR(); DEBUGF(("esock_ssl_write: calling SSL_write fd = %d\n" " state before: %s\n", cp->fd, SSL_state_string(ssl))); ret = SSL_write(ssl, buf, len); ssl_error = SSL_get_error(ssl, ret); DEBUGF((" SSL_write = %d\n" " ssl_error: %s\n" " state after: %s\n", ret, ssl_error_str(ssl_error), SSL_state_string(ssl))); if (ssl_error == SSL_ERROR_NONE) { DEBUGMSGF(("message (hex) : [%3.*a]\n", ret, buf)); DEBUGMSGF(("message (char): [%3.*b]\n", ret, buf)); } if (ret > 0) return ret; if (ret == 0) { check_shutdown(cp); return ret; } end_ssl_call(ret, cp, ssl_error); return ret;}int esock_ssl_shutdown(Connection *cp){ int ret, ssl_error; SSL *ssl = cp->opaque; RESET_ERRSTR(); DEBUGF(("esock_ssl_shutdown: calling SSL_shutdown fd = %d\n" " state before: %s\n", cp->fd, SSL_state_string(ssl))); ret = SSL_shutdown(ssl); ssl_error = SSL_get_error(ssl, ret); DEBUGF((" SSL_shutdown = %d\n" " ssl_error: %s\n" " state after: %s\n", ret, ssl_error_str(ssl_error), SSL_state_string(ssl))); if (ret >= 0) { check_shutdown(cp); return ret; } end_ssl_call(ret, cp, ssl_error); return ret;}/* Returns total number of bytes in DER encoded cert pointed to by * *buf, which is allocated by this function, unless return < 0. * XXX X509_free ?? */int esock_ssl_getpeercert(Connection *cp, unsigned char **buf){ int len; SSL *ssl = cp->opaque; X509 *x509; unsigned char *tmp; RESET_ERRSTR(); if((x509 = SSL_get_peer_certificate(ssl)) == NULL) { MAYBE_SET_ERRSTR("enopeercert"); /* XXX doc */ return -1; } if ((len = i2d_X509(x509, NULL)) <= 0) { MAYBE_SET_ERRSTR("epeercert"); return -1; } tmp = *buf = esock_malloc(len); /* We must use a temporary value here, since i2d_X509(X509 *x, * unsigned char **out) increments *out. */ if (i2d_X509(x509, &tmp) < 0) { esock_free(tmp); MAYBE_SET_ERRSTR("epeercert"); return -1; } return len;}/* Returns total number of bytes in chain of certs. Each cert begins * with a 4-bytes length. The last cert is ended with 4-bytes of * zeros. The result is returned in *buf, which is allocated unless * the return value is < 0. * XXX X509_free ? sk_X509_free ? * XXX X509_free is reference counting. */int esock_ssl_getpeercertchain(Connection *cp, unsigned char **buf){ SSL *ssl = cp->opaque; STACK_OF(X509) *x509_stack; X509 *x509; int num, i, totlen, pos, *der_len; unsigned char *vbuf; RESET_ERRSTR(); if((x509_stack = SSL_get_peer_cert_chain(ssl)) == NULL) { MAYBE_SET_ERRSTR("enopeercertchain"); /* XXX doc */ return -1; } num = sk_X509_num(x509_stack); der_len = esock_malloc(num * sizeof(int)); totlen = 0; for (i = 0; i < num; i++) { x509 = sk_X509_value(x509_stack, i); totlen += 4; if ((der_len[i] = i2d_X509(x509, NULL)) < 0) { MAYBE_SET_ERRSTR("epeercertchain"); esock_free(der_len); return -1; } totlen += der_len[i]; } totlen += 4; vbuf = *buf = esock_malloc(totlen); pos = 0; for (i = 0; i < num; i++) { x509 = sk_X509_value(x509_stack, i); PUT_INT32(der_len[i], vbuf); vbuf += 4; /* Note: i2d_X509 increments vbuf */ if (i2d_X509(x509, &vbuf) < 0) { MAYBE_SET_ERRSTR("epeercertchain"); esock_free(*buf); esock_free(der_len); return -1; } } esock_free(der_len); return totlen;}int esock_ssl_getprotocol_version(Connection *cp, char **buf){ SSL *ssl = cp->opaque; RESET_ERRSTR(); if (!ssl) { MAYBE_SET_ERRSTR("enoent"); return -1; } *buf = (char *) SSL_get_version(ssl); return 0;}int esock_ssl_getcipher(Connection *cp, char **buf){ SSL *ssl = cp->opaque; RESET_ERRSTR(); if (!ssl) { MAYBE_SET_ERRSTR("enoent"); return -1; } *buf = (char *) SSL_get_cipher(ssl); return 0;}/* Local functions */static char *ssl_error_str(int ssl_error){ int i; static char buf[128]; for (i = 0; i < sizeof(errs)/sizeof(err_entry); i ++) { if (ssl_error == errs[i].code) return errs[i].text; } sprintf(buf, "esock_openssl: SSL_error unknown: %d", ssl_error); return buf;}void end_ssl_call(int ret, Connection *cp, int ssl_error){ SET_WANT(cp, ssl_error); switch (ssl_error) { case SSL_ERROR_SYSCALL: /* Typically sock_errno() is equal to ERRNO_BLOCK */ MAYBE_SET_ERRSTR(esock_posix_str(sock_errno())); break; case SSL_ERROR_SSL: sock_set_errno(ERRNO_NONE); MAYBE_SET_ERRSTR("esslerrssl"); break; case SSL_ERROR_WANT_X509_LOOKUP: SSLDEBUGF(); sock_set_errno(ERRNO_NONE); MAYBE_SET_ERRSTR("ex509lookup"); break; case SSL_ERROR_WANT_CONNECT: SSLDEBUGF(); sock_set_errno(ERRNO_NONE); MAYBE_SET_ERRSTR("ewantconnect"); break; default: break; }}void check_shutdown(Connection *cp) { int sd_mode; SSL *ssl = cp->opaque; sd_mode = SSL_get_shutdown(ssl); if (sd_mode & SSL_RECEIVED_SHUTDOWN) cp->eof = 1; if (sd_mode & SSL_SENT_SHUTDOWN) { DEBUGF(("check_shutdown SSL_SENT_SHUTDOWN\n")); cp->bp = 1; }}/* * set_ssl_parameters * * Set ssl parameters from connection structure. Only called for * listen and connect. * * Note: The -cacertdir option is not documented. */static int set_ssl_parameters(Connection *cp, SSL_CTX *ctx){ char *cacertfile = NULL, *cacertdir = NULL, *certfile = NULL; char *keyfile = NULL, *ciphers = NULL, *password = NULL; int verify = 0, verify_depth = DEFAULT_VERIFY_DEPTH, verify_mode; int i, argc; char **argv; callback_data *cb_data; RESET_ERRSTR(); argc = esock_build_argv(cp->flags, &argv); DEBUGF(("Argv:\n")); for (i = 0; i < argc; i++) { DEBUGF(("%d: %s\n", i, argv[i])); } for (i = 0; i < argc; i++) { if (strcmp(argv[i], "-verify") == 0) { verify = atoi(argv[++i]); } else if (strcmp(argv[i], "-depth") == 0) { verify_depth = atoi(argv[++i]); } else if (strcmp(argv[i], "-log") == 0) { /* XXX ignored: logging per connection not supported */ i++; } else if (strcmp(argv[i], "-certfile") == 0) { certfile = argv[++i]; } else if (strcmp(argv[i], "-keyfile") == 0) { keyfile = argv[++i]; } else if (strcmp(argv[i], "-password") == 0) { password = argv[++i]; } else if (strcmp(argv[i], "-cacertfile") == 0) { cacertfile = argv[++i]; } else if (strcmp(argv[i], "-cacertdir") == 0) { cacertdir = argv[++i]; } else if (strcmp(argv[i], "-d") == 0) { /* XXX ignored: debug per connection not supported */ i++; } else if (strcmp(argv[i], "-ciphers") == 0) { ciphers = argv[++i]; } else { /* XXX Error: now ignored */ } } DEBUGF(("set_ssl_parameters: all arguments read\n")); if (cp->origin == ORIG_LISTEN && !certfile) { DEBUGF(("ERROR: Server must have certificate\n")); MAYBE_SET_ERRSTR("enoservercert"); goto err_end; } /* Define callback data */ /* XXX Check for NULL */ cb_data = esock_malloc(sizeof(callback_data)); cb_data->ctx = ctx; if (password) { cb_data->passwd = esock_malloc(strlen(password) + 1); strcpy(cb_data->passwd, password); } else cb_data->passwd = NULL; cb_data->verify_depth = verify_depth; SSL_CTX_set_ex_data(ctx, callback_data_index, cb_data); /* password callback */ SSL_CTX_set_default_passwd_cb(ctx, passwd_callback); SSL_CTX_set_default_passwd_cb_userdata(ctx, cb_data); /* Set location for "trusted" certificates */ if (cacertfile || cacertdir) { int res; DEBUGF(("set_ssl_parameters: SSL_CTX_load_verify_locations\n")); FOPEN_WORKAROUND(res, SSL_CTX_load_verify_locations(ctx, cacertfile, cacertdir)); if (!res) { DEBUGF(("ERROR: Cannot load verify locations\n")); MAYBE_SET_ERRSTR("ecacertfile"); goto err_end; } } else { int res; DEBUGF(("set_ssl_parameters: SSL_CTX_set_default_verify_paths\n")); FOPEN_WORKAROUND(res, SSL_CTX_set_default_verify_paths(ctx)); if (!res) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?