diff options
Diffstat (limited to 'lib/libostp')
-rw-r--r-- | lib/libostp/auth.c | 95 | ||||
-rw-r--r-- | lib/libostp/server.c | 1 | ||||
-rw-r--r-- | lib/libostp/session.c | 42 |
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"); |