<div dir="ltr">Hi Everyone,<div><br></div><div>I need help to get my nopoll wss server to accept PSK connections with OpenSSL. Is this supported? I had it working with certificates but I need both. Any help would be fantastic, I've been stuck on this for hours..</div><div><br></div><div>Client hangs on call to nopoll_conn_wait_until_connection_ready until it times out.</div><div>This is how I was trying it (note: some irrelevant functions missing) :<br><br>server.c</div><div><br></div><div><div>guint psk_server_cb(SSL *ssl, const gchar *identity, guchar *psk, guint max_psk_len)</div><div>{</div><div>    guint8 psk2[16] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10};</div><div>    printf("Identity: %s, Max Length: %d\n", identity, max_psk_len);</div><div>    memcpy(psk, psk2, 16);</div><div>    return 16;</div><div>}</div><div><br></div><div>void initialize_ssl()</div><div>{</div><div><span class="" style="white-space:pre">  </span>printf("Entering %s\n", __FUNCTION__);</div><div>    const SSL_METHOD *method;</div><div>    SSL_library_init();</div><div>    SSL_load_error_strings();</div><div>    OpenSSL_add_all_algorithms();</div><div>    method = TLSv1_server_method();</div><div>    openssl_ctx = SSL_CTX_new(method);</div><div>    SSL_CTX_set_psk_server_callback(openssl_ctx, psk_server_cb);</div><div>    SSL_CTX_use_psk_identity_hint(openssl_ctx, NULL);</div><div>    SSL_CTX_set_verify(openssl_ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT|SSL_VERIFY_CLIENT_ONCE, cert_server_cb);</div><div>    SSL_CTX_use_certificate_file(openssl_ctx, CERTFILE, SSL_FILETYPE_PEM);</div><div>    SSL_CTX_use_PrivateKey_file(openssl_ctx, KEYFILE, SSL_FILETYPE_PEM);</div><div>    if(SSL_CTX_set_cipher_list(openssl_ctx, CIPHERS) == 0)</div><div>    {</div><div>        printf("Fail to select ciphers\n");</div><div>        exit(1);</div><div>    }</div><div>    if(openssl_ctx == NULL)</div><div>    {</div><div>        printf("CTX Error\n");</div><div>        exit(1);</div><div>    }</div><div>    printf("Exiting %s\n", __FUNCTION__);</div><div>    return;</div><div>}</div></div><div><br></div><div><div>SSL_CTX * ip_control_ssl_ctx_creator (noPollCtx * ctx, noPollConn * conn, noPollConnOpts * opts, nopoll_bool is_client, noPollPtr user_data)</div><div>{</div><div><span class="" style="white-space:pre">       </span>printf("Entering %s\n", __FUNCTION__);</div><div><span class="" style="white-space:pre">   </span>// Initialize OPENSSL SSL_CTX</div><div><span class="" style="white-space:pre">      </span>initialize_ssl();</div><div><span class="" style="white-space:pre">  </span>return openssl_ctx;</div><div>}</div><div><br></div><div>nopoll_bool onReady(noPollCtx * ctx, noPollConn * conn, noPollPtr  user_data)</div><div>{</div><div><span class="" style="white-space:pre">  </span>printf("Ready\n");</div><div><span class="" style="white-space:pre">       </span>return nopoll_true;</div><div>}</div></div><div><br></div><div><div>gint main(gint argc, const gchar *argv[])</div><div>{</div><div><span class="" style="white-space:pre">        </span>// Declaration of noPoll objects</div><div><span class="" style="white-space:pre">   </span>noPollCtx *ctx;</div><div><span class="" style="white-space:pre">    </span>noPollConn *conn;</div><div><span class="" style="white-space:pre">  </span>noPollConnOpts *opts;</div><div><span class="" style="white-space:pre">      </span>NOPOLL_SOCKET sockfd;</div><div><span class="" style="white-space:pre">      </span>struct sockaddr_in server;</div><div><br></div><div><span class="" style="white-space:pre">        </span>// Initialize noPollCtx</div><div><span class="" style="white-space:pre">    </span>ctx = nopoll_ctx_new();</div><div><br></div><div><span class="" style="white-space:pre">   </span>// Initialize noPollConnOpts</div><div><span class="" style="white-space:pre">       </span>opts = nopoll_conn_opts_new();</div><div><br></div><div><span class="" style="white-space:pre">    </span>// Set ssl creator</div><div><span class="" style="white-space:pre"> </span>nopoll_ctx_set_ssl_context_creator(ctx, (noPollSslContextCreator)ip_control_ssl_ctx_creator, NULL);</div><div><br></div><div><span class="" style="white-space:pre">       </span>// Add cert to opts</div><div><span class="" style="white-space:pre">        </span>if(!nopoll_conn_opts_set_ssl_certs(opts, CERTFILE, KEYFILE, NULL, NULL))</div><div><span class="" style="white-space:pre">   </span>{</div><div><span class="" style="white-space:pre">          </span>printf("Error loading certificate / key\n");</div><div><span class="" style="white-space:pre">             </span>return 1;</div><div><span class="" style="white-space:pre">  </span>}</div><div><br></div><div><span class="" style="white-space:pre"> </span>// Set ssl protocol</div><div><span class="" style="white-space:pre">        </span>nopoll_conn_opts_set_ssl_protocol (opts, NOPOLL_METHOD_TLSV1);</div><div><br></div><div><span class="" style="white-space:pre">    </span>// Set up listener</div><div><span class="" style="white-space:pre"> </span>printf("Starting listener on port %s:\n", PORT);</div><div><span class="" style="white-space:pre"> </span>noPollConn * listener = nopoll_listener_tls_new_opts (ctx, opts, "0.0.0.0", PORT);</div><div><span class="" style="white-space:pre">       </span>if (! nopoll_conn_is_ok (listener)) {</div><div>     <span class="" style="white-space:pre">      </span>printf("Unsuccessful listener\n");</div><div>     <span class="" style="white-space:pre">       </span>return 1;</div><div><span class="" style="white-space:pre">  </span>}</div><div><br></div><div><span class="" style="white-space:pre"> </span>nopoll_log_enable(ctx, nopoll_true);</div><div><span class="" style="white-space:pre">       </span>// Set onReady function</div><div><span class="" style="white-space:pre">    </span>nopoll_ctx_set_on_ready(ctx, onReady, NULL);</div><div><br></div><div><span class="" style="white-space:pre">      </span>// Set onMessage function</div><div><span class="" style="white-space:pre">  </span>nopoll_ctx_set_on_msg(ctx, onMessage, NULL);</div><div><br></div><div><br></div><div><span class="" style="white-space:pre">     </span>// Set loop</div><div><span class="" style="white-space:pre">        </span>nopoll_loop_wait(ctx, 0);</div><div><br></div><div><br></div><div><span class="" style="white-space:pre">        </span>// Unreference noPoll objects</div><div><span class="" style="white-space:pre">      </span>nopoll_conn_opts_unref(opts);</div><div><span class="" style="white-space:pre">      </span>nopoll_ctx_unref(ctx);</div><div><span class="" style="white-space:pre">     </span>return 0;</div><div>}</div></div><div><br></div><div><br></div><div>client:</div><div><br></div><div><div>guint psk_client_cb(SSL *ssl, const gchar *hint, gchar *identity, guint max_identity_len, guint8 *psk, guint max_psk_len)</div><div>{</div><div><span class="" style="white-space:pre">  </span>printf("psk_client_cb\n");</div><div>    guint8 psk2[16] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10};</div><div><span class="" style="white-space:pre">      </span>strcpy(identity, "CHRIS\0");</div><div>    printf("Identity: %s, Max Length: %d\n", identity, max_psk_len);</div><div>    memcpy(psk, psk2, 16);</div><div><span class="" style="white-space:pre">   </span>return 16;</div><div>}</div><div><br></div><div>void initialize_ssl()</div><div>{</div><div><span class="" style="white-space:pre">    </span>gint i;</div><div>    guint8 md[32];</div><div>    guint n;</div><div><span class="" style="white-space:pre">    </span>printf("Entering %s\n", __FUNCTION__);</div><div>    const SSL_METHOD *method;</div><div>    SSL_library_init();</div><div>    SSL_load_error_strings();</div><div>    OpenSSL_add_all_algorithms();</div><div>    method = TLSv1_client_method();</div><div>    openssl_ctx = SSL_CTX_new(method);</div><div>    SSL_CTX_set_verify(openssl_ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, cert_client_cb);</div><div>    SSL_CTX_set_psk_client_callback(openssl_ctx, psk_client_cb);</div><div>    SSL_CTX_use_certificate_file(openssl_ctx, CERTFILE, SSL_FILETYPE_PEM);</div><div>    SSL_CTX_use_PrivateKey_file(openssl_ctx, KEYFILE, SSL_FILETYPE_PEM);</div><div>    if(SSL_CTX_set_cipher_list(openssl_ctx, CIPHERS) == 0)</div><div>    {</div><div>        printf("Fail to select ciphers\n");</div><div>        exit(1);</div><div>    }</div><div>    if(openssl_ctx == NULL)</div><div>    {</div><div>        printf("CTX Error\n");</div><div>        exit(1);</div><div>    }</div><div>    printf("Exiting %s\n", __FUNCTION__);</div><div>    return;</div><div>}</div></div><div><br></div><div><div>SSL_CTX * ip_control_ssl_ctx_creator (noPollCtx * ctx, noPollConn * conn, noPollConnOpts * opts, nopoll_bool is_client, noPollPtr user_data)</div><div>{</div><div><span class="" style="white-space:pre">    </span>printf("Entering %s\n", __FUNCTION__);</div><div><span class="" style="white-space:pre">   </span>return openssl_ctx;</div><div>}</div></div><div><br></div><div><div>int main(int argc, const char *argv[])</div><div>{</div><div><span class="" style="white-space:pre">   </span>// Declaration of noPoll objects</div><div><span class="" style="white-space:pre">   </span>noPollCtx *ctx;</div><div><span class="" style="white-space:pre">    </span>noPollConn *conn;</div><div><span class="" style="white-space:pre">  </span>noPollConnOpts *opts;</div><div><span class="" style="white-space:pre">      </span></div><div><span class="" style="white-space:pre">   </span>CIPHERS = "PSK-AES128-GCM-SHA256:PSK-AES128-CBC-SHA";</div><div><br></div><div><span class="" style="white-space:pre">   </span>// Initialize OPENSSL SSL_CTX</div><div><span class="" style="white-space:pre">      </span>initialize_ssl();</div><div><br></div><div><span class="" style="white-space:pre"> </span>// Initialize noPollCtx</div><div><span class="" style="white-space:pre">    </span>ctx = nopoll_ctx_new();</div><div><br></div><div><span class="" style="white-space:pre">   </span>// Initialize noPollConnOpts</div><div><span class="" style="white-space:pre">       </span>opts = nopoll_conn_opts_new();</div><div><br></div><div><span class="" style="white-space:pre">    </span>// Set onMessage function</div><div><span class="" style="white-space:pre">  </span>nopoll_ctx_set_on_msg(ctx, onMessage, NULL);</div><div><br></div><div><br></div><div><span class="" style="white-space:pre">     </span>// Set ssl creator</div><div><span class="" style="white-space:pre"> </span>nopoll_ctx_set_ssl_context_creator(ctx, (noPollSslContextCreator)ip_control_ssl_ctx_creator, NULL);</div><div><br></div><div><span class="" style="white-space:pre">       </span>nopoll_log_enable(ctx, nopoll_true);</div><div><br></div><div><span class="" style="white-space:pre">      </span>// Connect to server & send message</div><div><span class="" style="white-space:pre">    </span>conn = nopoll_conn_tls_new(ctx, opts, "0.0.0.0", PORT, NULL, NULL, NULL, NULL);</div><div><span class="" style="white-space:pre">  </span>if(!nopoll_conn_is_ok(conn))</div><div><span class="" style="white-space:pre">       </span>{</div><div><span class="" style="white-space:pre">          </span>printf("Error connecting\n");</div><div><span class="" style="white-space:pre">            </span>return 1;</div><div><span class="" style="white-space:pre">  </span>}</div><div><span class="" style="white-space:pre">  </span>if(!nopoll_conn_wait_until_connection_ready(conn,100000))</div><div><span class="" style="white-space:pre">  </span>{</div><div><span class="" style="white-space:pre">          </span>printf("Timeout occured\n");</div><div><span class="" style="white-space:pre">             </span>return 1;</div><div><span class="" style="white-space:pre">  </span>}</div><div><span class="" style="white-space:pre">  </span>// Send message</div><div><span class="" style="white-space:pre">    </span>if(nopoll_conn_send_text(conn, "Hello There!", 12) != 12)</div><div><span class="" style="white-space:pre">        </span>{</div><div><span class="" style="white-space:pre">          </span>printf("Write error\n");</div><div><span class="" style="white-space:pre">         </span>return 1;</div><div><span class="" style="white-space:pre">  </span>}</div><div><br></div><div><span class="" style="white-space:pre"> </span>// Set wait for response</div><div><span class="" style="white-space:pre">   </span>nopoll_loop_wait(ctx, 5);</div><div><br></div><div><br></div><div><span class="" style="white-space:pre">        </span>// Unreference noPoll objects</div><div><span class="" style="white-space:pre">      </span>json_decref(root);</div><div><span class="" style="white-space:pre"> </span>nopoll_conn_opts_unref(opts);</div><div><span class="" style="white-space:pre">      </span>nopoll_ctx_unref(ctx);</div><div><span class="" style="white-space:pre">     </span>return 0;</div><div>}</div></div><div><br></div><div><br></div><div><br></div><div><br></div><div>OUTPUT FROM SERVER:<br><div>Starting listener on port 8091:</div><div>(proc 4000): (debug)nopoll_conn.c:3823 Calling to accept web socket connection over master id=2, socket=3</div><div>(proc 4000): (debug)nopoll_ctx.c:257 registered connection id 3, role: 2</div><div>(proc 4000): (debug)nopoll_listener.c:410 Listener created, started: <a href="http://127.0.0.1:35813">127.0.0.1:35813</a> (socket: 4)</div><div>(proc 4000): (debug)nopoll_conn.c:1602 Releasing connection id 3 reference, current ref count status is: 1</div><div>(proc 4000): (debug)nopoll_conn.c:3867 Accepted new WebSocket conn-id=3, socket=4, over master id=2, socket=3</div><div>(proc 4000): (debug)nopoll_conn.c:3921 Connection received and accepted from <a href="http://0.0.0.0:8091">0.0.0.0:8091</a> (conn refs: 2, ctx refs: 3)</div><div>(proc 4000): (debug)nopoll_conn.c:3932 Starting TLS process, options=0xa7a0f0, listener=0xa7a590</div><div>Entering ip_control_ssl_ctx_creator</div><div>Entering initialize_ssl</div><div>Exiting initialize_ssl</div><div>(proc 4000): (debug)nopoll_conn.c:4004 Using certificate file: ./cert.pem (with ssl context ref: 0xa97580)</div><div>(proc 4000): (debug)nopoll_conn.c:4023 Using certificate key: ./key.pem</div><div>(proc 4000): (debug)nopoll_conn.c:4084 Prepared TLS session to be activated on next reads (conn id 3)</div><div>(proc 4000): (debug)nopoll_conn.c:2518 === START: conn-id=3 (errno=2, session: 4, conn->handshake_ok: 0, conn->pending_ssl_accept: 1) ===</div><div>(proc 4000): (debug)nopoll_conn.c:2523 Received connect over a connection (id 3) with TLS handshake pending to be finished, processing..</div><div>(proc 4000): (warning)nopoll_conn.c:2531 accept function have failed (for listener side) ssl_error=2 : dumping error stack..</div><div>(proc 4000): (warning)nopoll_conn.c:2536 still not prepared to continue because read wanted conn-id=3 (0xa7a8e0, session 4)</div><div>(proc 4000): (debug)nopoll_conn.c:2518 === START: conn-id=3 (errno=11, session: 4, conn->handshake_ok: 0, conn->pending_ssl_accept: 1) ===</div><div>(proc 4000): (debug)nopoll_conn.c:2523 Received connect over a connection (id 3) with TLS handshake pending to be finished, processing..</div><div>Identity: CHRIS, Max Length: 516</div><div>(proc 4000): (debug)nopoll_conn.c:2560 Completed TLS operation from <a href="http://127.0.0.1:35813">127.0.0.1:35813</a> (conn id 3, ssl veriry result: 0)</div><div>(proc 4000): (debug)nopoll_conn.c:2518 === START: conn-id=3 (errno=11, session: 4, conn->handshake_ok: 0, conn->pending_ssl_accept: 0) ===</div><div>(proc 4000): (debug)nopoll_conn.c:2592 Connection id 3 handshake is not complete, running..</div><div>(proc 4000): (debug)nopoll_conn.c:2416 Checking to complete conn-id=3 WebSocket handshake, role 2</div><div>(proc 4000): (critical) nopoll_conn.c:385 SSL socket closed on SSL_read (res=0, ssl_err=5, errno=0)</div><div>(proc 4000): (critical) nopoll_conn.c:347     noPoll id=3, socket: 4 (after testing errno: 0)</div><div>(proc 4000): (critical) nopoll_conn.c:2429 Unexpected connection close during handshake..closing connection</div><div>(proc 4000): (debug)nopoll_conn.c:1436 shutting down connection id=3 (session: 4, role: listener)</div><div>(proc 4000): (debug)nopoll_conn.c:1602 Releasing connection id 3 reference, current ref count status is: 0</div><div>(proc 4000): (debug)nopoll_conn.c:1617 Released context refs, now: 3</div></div><div><br></div><div>OUTPUT FROM CLIENT:</div><div><div>(proc 4001): (debug)nopoll_conn.c:2436 No more data available on connection id 2</div><div>(proc 4001): (debug)nopoll_conn.c:2416 Checking to complete conn-id=2 WebSocket handshake, role 1</div><div>(proc 4001): (debug)nopoll_conn.c:2436 No more data available on connection id 2</div><div>(proc 4001): (debug)nopoll_conn.c:2416 Checking to complete conn-id=2 WebSocket handshake, role 1</div><div>(proc 4001): (debug)nopoll_conn.c:2436 No more data available on connection id 2</div><div>(proc 4001): (debug)nopoll_conn.c:2416 Checking to complete conn-id=2 WebSocket handshake, role 1</div><div>(proc 4001): (debug)nopoll_conn.c:2436 No more data available on connection id 2</div><div>(proc 4001): (debug)nopoll_conn.c:2416 Checking to complete conn-id=2 WebSocket handshake, role 1</div><div>(proc 4001): (debug)nopoll_conn.c:2436 No more data available on connection id 2</div><div>(proc 4001): (debug)nopoll_conn.c:2416 Checking to complete conn-id=2 WebSocket handshake, role 1</div><div>(proc 4001): (debug)nopoll_conn.c:2436 No more data available on connection id 2</div><div>(proc 4001): (debug)nopoll_conn.c:2416 Checking to complete conn-id=2 WebSocket handshake, role 1</div><div>(proc 4001): (debug)nopoll_conn.c:2436 No more data available on connection id 2</div><div>(proc 4001): (debug)nopoll_conn.c:2416 Checking to complete conn-id=2 WebSocket handshake, role 1</div><div>(proc 4001): (debug)nopoll_conn.c:2436 No more data available on connection id 2</div><div>(proc 4001): (debug)nopoll_conn.c:2416 Checking to complete conn-id=2 WebSocket handshake, role 1</div><div>(proc 4001): (debug)nopoll_conn.c:2436 No more data available on connection id 2</div><div>(proc 4001): (debug)nopoll_conn.c:2416 Checking to complete conn-id=2 WebSocket handshake, role 1</div><div>(proc 4001): (debug)nopoll_conn.c:2436 No more data available on connection id 2</div><div>(proc 4001): (debug)nopoll_conn.c:2416 Checking to complete conn-id=2 WebSocket handshake, role 1</div><div>(proc 4001): (debug)nopoll_conn.c:2436 No more data available on connection id 2</div><div>(proc 4001): (debug)nopoll_conn.c:2416 Checking to complete conn-id=2 WebSocket handshake, role 1</div><div>(proc 4001): (debug)nopoll_conn.c:2436 No more data available on connection id 2</div><div>(proc 4001): (debug)nopoll_conn.c:2416 Checking to complete conn-id=2 WebSocket handshake, role 1</div><div>(proc 4001): (debug)nopoll_conn.c:2436 No more data available on connection id 2</div><div>(proc 4001): (debug)nopoll_conn.c:2416 Checking to complete conn-id=2 WebSocket handshake, role 1</div><div>(proc 4001): (debug)nopoll_conn.c:2436 No more data available on connection id 2</div><div>(proc 4001): (debug)nopoll_conn.c:2416 Checking to complete conn-id=2 WebSocket handshake, role 1</div><div>(proc 4001): (debug)nopoll_conn.c:2436 No more data available on connection id 2</div><div>(proc 4001): (debug)nopoll_conn.c:2416 Checking to complete conn-id=2 WebSocket handshake, role 1</div><div>(proc 4001): (debug)nopoll_conn.c:2436 No more data available on connection id 2</div><div>(proc 4001): (debug)nopoll_conn.c:2416 Checking to complete conn-id=2 WebSocket handshake, role 1</div><div>(proc 4001): (debug)nopoll_conn.c:2436 No more data available on connection id 2</div><div>(proc 4001): (debug)nopoll_conn.c:2416 Checking to complete conn-id=2 WebSocket handshake, role 1</div><div>(proc 4001): (debug)nopoll_conn.c:2436 No more data available on connection id 2</div></div><div><br></div><div><br></div></div>