ssize_t SslSocket::read(x0::Buffer& result) { if (result.size() == result.capacity()) result.reserve(result.size() + 4096); ssize_t rv = gnutls_read(session_, result.end(), result.capacity() - result.size()); if (rv < 0) return rv; result.resize(result.size() + rv); return rv; }
bool DTLS_Decrypt(NetworkAddress * sourceAddress, uint8_t * encrypted, int encryptedLength, uint8_t * decryptBuffer, int decryptBufferLength, int * decryptedLength, void *context) { bool result = false; DTLS_Session * session = GetSession(sourceAddress); if (session) { session->Buffer = encrypted; session->BufferLength = encryptedLength; if (session->SessionEstablished) { *decryptedLength = gnutls_read(session->Session, decryptBuffer, decryptBufferLength); result = (*decryptedLength > 0); if (!result) { FreeSession(session); session = NULL; } } else { *decryptedLength = 0; session->SessionEstablished = (gnutls_handshake(session->Session) == GNUTLS_E_SUCCESS); if (session->SessionEstablished) Lwm2m_Info("Session established"); } } if (!session) { int index; for (index = 0;index < MAX_DTLS_SESSIONS; index++) { if (!sessions[index].Session) { SetupNewSession(index, sourceAddress, false); sessions[index].UserContext = context; gnutls_transport_set_push_function(sessions[index].Session, SSLSendCallBack); sessions[index].Buffer = encrypted; sessions[index].BufferLength = encryptedLength; sessions[index].SessionEstablished = (gnutls_handshake(sessions[index].Session) == GNUTLS_E_SUCCESS); break; } } } return result; }
ssize_t ConnSSL_Read(CONNECTION *c, void * buf, size_t count) { ssize_t br; Conn_OPTION_DEL(c, CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ); #ifdef HAVE_LIBSSL br = (ssize_t) SSL_read(c->ssl_state.ssl, buf, count); if (br > 0) /* on EOF we have to call ConnSSL_HandleError(), see SSL_read(3) */ return br; #endif #ifdef HAVE_LIBGNUTLS br = gnutls_read(c->ssl_state.gnutls_session, buf, count); if (br >= 0) /* on EOF we must _not_ call ConnSSL_HandleError, see gnutls_record_recv(3) */ return br; #endif /* error on read: switch ConnSSL_HandleError() return values -> 0 is "try again", so return -1 and set EAGAIN */ if (ConnSSL_HandleError(c, br, "ConnSSL_Read") == 0) { errno = EAGAIN; return -1; } return 0; }
/* the correct response to a return value of 0 is almost certainly tlscomm_close(scs): don't _expect() anything unless anything else would represent failure */ int tlscomm_expect(struct connection_state *scs, const char *prefix, char *linebuf, int buflen) { int prefixlen = (int) strlen(prefix); int buffered_bytes = 0; memset(linebuf, 0, buflen); TDM(DEBUG_INFO, "%s: expecting: %s\n", scs->name, prefix); /* if(scs->unprocessed[0]) { TDM(DEBUG_INFO, "%s: buffered: %s\n", scs->name, scs->unprocessed); } */ while (scs->unprocessed[0] != '\0' || wait_for_it(scs->sd, EXPECT_TIMEOUT)) { if (scs->unprocessed[buffered_bytes] == '\0') { int thisreadbytes; #ifdef USE_GNUTLS if (scs->tls_state) { /* BUF_SIZE - 1 leaves room for trailing \0 */ thisreadbytes = gnutls_read(scs->tls_state, &scs->unprocessed[buffered_bytes], BUF_SIZE - 1 - buffered_bytes); if (thisreadbytes < 0) { handle_gnutls_read_error(thisreadbytes, scs); return 0; } } else #endif { thisreadbytes = read(scs->sd, &scs->unprocessed[buffered_bytes], BUF_SIZE - 1 - buffered_bytes); if (thisreadbytes < 0) { TDM(DEBUG_ERROR, "%s: error reading: %s\n", scs->name, strerror(errno)); return 0; } } buffered_bytes += thisreadbytes; /* force null termination */ scs->unprocessed[buffered_bytes] = '\0'; if (buffered_bytes == 0) { return 0; /* bummer */ } } else { buffered_bytes = strlen(scs->unprocessed); } while (buffered_bytes >= prefixlen) { int linebytes; linebytes = getline_from_buffer(scs->unprocessed, linebuf, buflen); if (linebytes == 0) { buffered_bytes = 0; } else { buffered_bytes -= linebytes; if (strncmp(linebuf, prefix, prefixlen) == 0) { TDM(DEBUG_INFO, "%s: got: %*s", scs->name, linebytes, linebuf); return 1; /* got it! */ } TDM(DEBUG_INFO, "%s: dumped(%d/%d): %.*s", scs->name, linebytes, buffered_bytes, linebytes, linebuf); } } } if (buffered_bytes == -1) { TDM(DEBUG_INFO, "%s: timed out while expecting '%s'\n", scs->name, prefix); } else { TDM(DEBUG_ERROR, "%s: expecting: '%s', saw (%d): %s%s", scs->name, prefix, buffered_bytes, linebuf, /* only print the newline if the linebuf lacks it */ (linebuf[strlen(linebuf) - 1] == '\n') ? "\n" : ""); } return 0; /* wait_for_it failed */ }