aboutsummaryrefslogtreecommitdiff
path: root/lib/libostp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libostp')
-rw-r--r--lib/libostp/auth.c95
-rw-r--r--lib/libostp/server.c1
-rw-r--r--lib/libostp/session.c42
3 files changed, 137 insertions, 1 deletions
diff --git a/lib/libostp/auth.c b/lib/libostp/auth.c
index 5fa59e9..ddc17b8 100644
--- a/lib/libostp/auth.c
+++ b/lib/libostp/auth.c
@@ -30,8 +30,10 @@
#include <sys/wait.h>
#include <sys/socket.h>
#include <ostp/net/auth.h>
+#include <ostp/net/stpsession.h>
#include <ostp/crypto/ecdh.h>
#include <ostp/otconfig.h>
+#include <ostp/defs.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
@@ -133,6 +135,78 @@ send_motd(struct ostp_client *c, const unsigned char *session_key)
}
}
+static inline void
+populate_peer(struct ostp_client *c, struct peer *pp)
+{
+ memset(pp, 0, sizeof(*pp));
+ pp->port = htons(OSTP_PORT);
+ pp->pad[0] = 0xFF;
+ memcpy(pp->host, c->host, IP_LEN_MAX);
+}
+
+static int
+send_peerlist(struct ostp_listener *lp, struct ostp_client *c, struct ostp_session *s)
+{
+ struct ostp_client *c_cur, *c_tmp;
+ struct peer peer_cur;
+ struct peer_block pb_cur;
+ struct ostp_session *sp;
+ size_t peer_count;
+ int i, j, error;
+ int seq;
+
+ memset(&pb_cur, 0, sizeof(pb_cur));
+ peer_count = lp->client_count;
+ seq = (peer_count <= 16) ? 1 : (peer_count / PB_N_PEERS);
+ pb_cur.seq = seq;
+ printf("peer_count=%d, seq=%d\n", peer_count, pb_cur.seq);
+
+ /*
+ * Grab peers and prepare blocks until seq == 0
+ *
+ *
+ * lp->clients
+ * +-------------------+
+ * i=| | | | | | | | | | |
+ * +-------------------+
+ * 0,1,2,3,4,5,6,7,8,9 <--+
+ * |
+ * pb_cur.peers |
+ * +---------------+ | lp->clients can be bigger
+ * j=| | | | | | | | | |
+ * +---------------+ +
+ * 0,1,2,3,4,5,6,7 <---+-/
+ *
+ *
+ * lp->clients is one big contigious array
+ * of connected clients and is used internally
+ * by the server to manage connected users.
+ *
+ * During a session request, the client may request
+ * peer-to-peer mode by setting the 'P' bit. If accepted,
+ * we'll need to send one or more peer blocks back, containing
+ * a list of `PB_N_PEERS' peers max per block.
+ *
+ */
+ for (i = 0; i < PB_N_BLOCKS && seq > 0; ++i) {
+ for (j = 1; j < PB_N_PEERS && j < peer_count; ++j) {
+ populate_peer(&lp->clients[j], &peer_cur);
+ pb_cur.peers[j] = peer_cur;
+ }
+
+ --seq;
+ pb_cur.seq = seq;
+ sp = &c->session;
+ session_send(&pb_cur, sizeof(pb_cur), sp);
+
+ if (j >= lp->client_count) {
+ break;
+ }
+ }
+
+ return 0;
+}
+
int
handle_srq(struct ostp_client *c, struct ostp_listener *lp, struct session_request *srq)
{
@@ -140,12 +214,20 @@ handle_srq(struct ostp_client *c, struct ostp_listener *lp, struct session_reque
struct ostp_session *session;
int error;
+ /* Do we require the SRQ 'U' bit? */
if (REQUIRE_USER_AUTH && !ISSET(srq->options, SESSION_REQ_USER)) {
printf("User authentication enforced but client 'U' bit not set\n");
printf("Closing connection...\n");
return -1;
}
+ /* Don't use P2P if not enabled */
+ if (!ENABLE_P2P && !ISSET(srq->options, SESSION_REQ_P2P)) {
+ printf("P2P not enabled but client 'P' bit set\n");
+ printf("Closing connection...\n");
+ return -1;
+ }
+
/* Generate a new keypair if we have no link */
if (!g_have_link) {
if (gen_x25519_keypair(&keypair) < 0) {
@@ -183,6 +265,19 @@ handle_srq(struct ostp_client *c, struct ostp_listener *lp, struct session_reque
return -1;
}
+ /* Handle P2P requests */
+ if (ISSET(srq->options, SESSION_REQ_P2P)) {
+ /*
+ * Not an error but we want to send this down
+ * the callstack so everything is cleaned up
+ * and terminated properly.
+ *
+ * TODO: Figure something else out here maybe...
+ */
+ send_peerlist(lp, c, session);
+ return -1;
+ }
+
/* Handle any requested session parameters */
if ((error = negotiate_spw(c, session->session_key)) < 0) {
free_session_key(session->session_key);
diff --git a/lib/libostp/server.c b/lib/libostp/server.c
index 794eda0..61e89f7 100644
--- a/lib/libostp/server.c
+++ b/lib/libostp/server.c
@@ -199,6 +199,7 @@ listener_poll(struct ostp_listener *lp)
++lp->client_count;
ip = inet_ntoa(caddr.sin_addr);
+ memcpy(c->host, ip, strlen(ip) + 1);
printf("Incoming connection from %s\n", ip);
handle_client(&caddr, c, lp);
break;
diff --git a/lib/libostp/session.c b/lib/libostp/session.c
index 3843207..b61600f 100644
--- a/lib/libostp/session.c
+++ b/lib/libostp/session.c
@@ -193,6 +193,35 @@ recv_motd(int sockfd, const unsigned char *session_key)
printf("%s\n", buf);
}
+static void
+recv_peers(int sockfd, const unsigned char *session_key)
+{
+ struct peer_block pb;
+ struct peer peer;
+ int i, len;
+
+ memset(&pb, 0, sizeof(pb));
+ memset(&peer, 0, sizeof(peer));
+
+ /* Receive the peer block the server sends back */
+ if ((len = recv_frame(sockfd, sizeof(pb), session_key, &pb)) < 0) {
+ printf("Failed to recv peers...\n");
+ return;
+ }
+
+ printf("Got %d bytes...\n", len);
+ printf("seq=%x\n", pb.seq);
+
+ for (i = 0; i < PB_N_PEERS; ++i) {
+ peer = pb.peers[i];
+ if (peer.pad[0] != 0xFF) {
+ continue;
+ }
+
+ printf("Peer available @ %s:%d\n", peer.host, peer.port);
+ }
+}
+
int
session_new(const char *host, struct ostp_session *res)
{
@@ -233,7 +262,7 @@ session_new(const char *host, struct ostp_session *res)
* Setup the session request and add our public
* key to it. We also assume user authentication.
*/
- stp_sq.options = SESSION_REQ_USER;
+ stp_sq.options = (SESSION_REQ_USER | SESSION_REQ_P2P);
memcpy(stp_sq.pubkey, keypair.pubkey, sizeof(stp_sq.pubkey));
LOG("Sending session request...\n");
@@ -266,6 +295,17 @@ session_new(const char *host, struct ostp_session *res)
return error;
}
+ /*
+ * If we requested P2P, the server will respond
+ * with peer blocks.
+ */
+ if (ISSET(stp_sq.options, SESSION_REQ_P2P)) {
+ recv_peers(sockfd, session_key);
+ free_session_key(session_key);
+ close(sockfd);
+ return 0;
+ }
+
/* Send server SPW bits */
if ((error = client_negotiate_spw(sockfd, session_key)) < 0) {
LOG("Session Parameter Negotiation failed\n");