aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2024-09-26 14:57:08 -0400
committerIan Moffett <ian@osmora.org>2024-09-26 14:57:08 -0400
commitd382f150dcd1a4317a62c5af2412bd304b3bfee7 (patch)
tree9d2e2391d655fd559b92381c507f1581685a45d3
parent7e6fb4b9f82dc4c6f7815a3fc4c60f6084928722 (diff)
project: Introduce actual connections
Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r--client/main.c107
-rw-r--r--lib/include/net/param.h45
-rw-r--r--ostp.d/include/net/auth.h1
-rw-r--r--ostp.d/net/otd_auth.c37
-rw-r--r--ostp.d/net/otd_param.c97
5 files changed, 286 insertions, 1 deletions
diff --git a/client/main.c b/client/main.c
index e6fcb7a..6bc5a5e 100644
--- a/client/main.c
+++ b/client/main.c
@@ -28,8 +28,10 @@
*/
#include <net/stpsession.h>
+#include <net/param.h>
#include <crypto/ecdh.h>
#include <arpa/inet.h>
+#include <defs.h>
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
@@ -38,6 +40,13 @@
#define CENTRAL_SERVER "149.248.6.149"
#define OSTP_PORT 5352
+static const char *pap_codestr[] = {
+ [PAP_SUCCESS] = "success",
+ [PAP_BAD_SPW] = "bad SPW",
+ [PAP_BAD_PERMS] = "insufficient permissions",
+ [PAP_RESOURCE] = "server out of resources"
+};
+
static void
log_pubkey(uint8_t pubkey[])
{
@@ -51,11 +60,72 @@ log_pubkey(uint8_t pubkey[])
}
static int
+negotiate_spw(int sockfd, const unsigned char *session_key)
+{
+ struct aes_message am;
+ struct msg_frame msg_frame;
+ struct pap pap;
+ unsigned char *tmp;
+ int error;
+
+ /* Create a PAP and encrypt it */
+ pap.spw = 0x8000;
+ pap.code = 0;
+
+ while (1) {
+ if ((error = send_frame(sockfd, &pap, sizeof(pap), session_key)) < 0) {
+ return error;
+ }
+
+ /* Receive the PAP the server replies with */
+ if ((error = recv_frame(sockfd, sizeof(pap), session_key, &pap)) < 0) {
+ return error;
+ }
+
+ /*
+ * If the server echos our PAP with code 0 then it has
+ * applied our session parameters! However, there is
+ * a chance arbitration will be needed and we need
+ * to look out for that too...
+ */
+ if (pap.code == 0) {
+ printf("** Negotiation success\n");
+ break;
+ }
+
+ printf("** Arbitration needed, server says: %s\n", pap_codestr[pap.code]);
+ printf("** Server proposes SPW of 0x%0X, accepting\n", pap.spw);
+ pap.spw |= PAP_SPW_QSR;
+ pap.code = 0;
+ }
+
+ return 0;
+}
+
+static void
+recv_motd(int sockfd, const unsigned char *session_key)
+{
+ char buf[4096];
+ int len;
+
+ /* Receive the PAP the server replies with */
+ if ((len = recv_frame(sockfd, sizeof(buf), session_key, buf)) < 0) {
+ printf("Failed to recv MOTD...\n");
+ return;
+ }
+
+ buf[len] = '\0';
+ printf("%s\n", buf);
+}
+
+static int
request_session(void)
{
struct sockaddr_in addr;
struct session_request stp_sq;
struct x25519_keypair keypair;
+ unsigned char serv_pubkey[32];
+ unsigned char *session_key;
int error, sockfd;
addr.sin_family = AF_INET;
@@ -95,7 +165,42 @@ request_session(void)
log_pubkey(keypair.pubkey);
printf("Sending session request...\n");
- send(sockfd, &stp_sq, sizeof(stp_sq), 0);
+ error = send(sockfd, &stp_sq, sizeof(stp_sq), 0);
+ if (error < 0) {
+ perror("Failed to send session request");
+ close(sockfd);
+ return error;
+ }
+
+ error = recv(sockfd, serv_pubkey, sizeof(serv_pubkey), 0);
+ if (error < 0) {
+ perror("Failed to get public key from peer\n");
+ close(sockfd);
+ return error;
+ }
+
+ if (error == 0) {
+ printf("Connection closed by peer\n");
+ close(sockfd);
+ return 0;
+ }
+
+ printf("Got public key from server\n");
+ log_pubkey(serv_pubkey);
+
+ printf("Deriving session key...\n");
+ gen_session_key(keypair.privkey, serv_pubkey, &session_key);
+
+ /* Send server SPW bits */
+ if ((error = negotiate_spw(sockfd, session_key)) < 0) {
+ printf("Session Parameter Negotiation failed\n");
+ free_session_key(session_key);
+ close(sockfd);
+ return error;
+ }
+
+ recv_motd(sockfd, session_key);
+ free_session_key(session_key);
close(sockfd);
return 0;
}
diff --git a/lib/include/net/param.h b/lib/include/net/param.h
new file mode 100644
index 0000000..ba2a0a2
--- /dev/null
+++ b/lib/include/net/param.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef NET_PARAM_H_
+#define NET_PARAM_H_
+
+#include <stdint.h>
+#include <defs.h>
+
+/*
+ * The Parameter Arbitration Packet which is crucial
+ * for Session Parameter Negotiation and Arbitration.
+ */
+struct pap {
+ uint16_t spw; /* Session parameter word */
+ uint8_t code; /* Specific code for packet */
+};
+
+#endif /* NET_PARAM_H_ */
diff --git a/ostp.d/include/net/auth.h b/ostp.d/include/net/auth.h
index 752bfe2..76567c3 100644
--- a/ostp.d/include/net/auth.h
+++ b/ostp.d/include/net/auth.h
@@ -33,5 +33,6 @@
#include <net/stpsession.h>
int handle_srq(int client_fd, struct session_request *srq);
+int negotiate_spw(int client_fd, unsigned char *session_key);
#endif /* NET_AUTH_H_ */
diff --git a/ostp.d/net/otd_auth.c b/ostp.d/net/otd_auth.c
index 3511e0c..6e757ae 100644
--- a/ostp.d/net/otd_auth.c
+++ b/ostp.d/net/otd_auth.c
@@ -27,9 +27,12 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <arpa/inet.h>
#include <net/auth.h>
+#include <net/param.h>
#include <net/stpsession.h>
#include <crypto/ecdh.h>
+#include <otconfig.h>
#include <stdio.h>
#define KEY_BYTE_WIDTH 32
@@ -47,6 +50,17 @@ log_pubkey(uint8_t pubkey[KEY_BYTE_WIDTH])
printf("\n");
}
+static void
+send_motd(int client_fd, const unsigned char *session_key)
+{
+ char motd[] = MOTD;
+
+ printf("Sending MOTD...\n");
+ if (send_frame(client_fd, motd, sizeof(motd), session_key) < 0) {
+ printf("Failed to session MOTD\n");
+ }
+}
+
/*
* Verify the session request packet and handle
* the rest.
@@ -58,6 +72,8 @@ int
handle_srq(int client_fd, struct session_request *srq)
{
struct x25519_keypair keypair;
+ unsigned char *session_key;
+ int error;
printf("Got public key from peer: \n");
log_pubkey(srq->pubkey);
@@ -68,5 +84,26 @@ handle_srq(int client_fd, struct session_request *srq)
return -1;
}
+ /* Send back our our public key */
+ error = send(client_fd, keypair.pubkey, keypair.pubkey_len, 0);
+ if (error < 0) {
+ perror("Failed to send public key");
+ return error;
+ }
+
+ printf("Deriving session key...\n");
+ error = gen_session_key(keypair.privkey, srq->pubkey, &session_key);
+ if (error < 0) {
+ return error;
+ }
+
+ /* Handle any requested session parameters */
+ if ((error = negotiate_spw(client_fd, session_key)) < 0) {
+ free_session_key(session_key);
+ return error;
+ }
+
+ send_motd(client_fd, session_key);
+ free_session_key(session_key);
return 0;
}
diff --git a/ostp.d/net/otd_param.c b/ostp.d/net/otd_param.c
new file mode 100644
index 0000000..fe33bd8
--- /dev/null
+++ b/ostp.d/net/otd_param.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <net/stpsession.h>
+#include <net/param.h>
+#include <crypto/aes.h>
+#include <otconfig.h>
+#include <defs.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+static int
+handle_pap(int client_fd, const struct pap *pap, const unsigned char *session_key)
+{
+ int error = 0;
+ uint8_t attempts = 0;
+ struct pap tmp_pap = *pap;
+ const size_t LEN = sizeof(struct pap);
+
+ /* TODO: Support more SPW bits */
+ while (1) {
+ /* Quick session request, jump right in! */
+ if (ISSET(tmp_pap.spw, PAP_SPW_QSR)) {
+ printf("Got QSR, starting session...\n");
+ send_frame(client_fd, &tmp_pap, LEN, session_key);
+ return 0;
+ }
+
+ /* We have exhausted our attempts */
+ if (attempts >= ARBITRATION_MAX) {
+ printf("Too many arbitration attempts, bailing!\n");
+ return -1;
+ }
+
+ printf("Got bad SPW from client\n");
+ printf("Attempting arbitration...\n");
+
+ tmp_pap.spw = 0x0;
+ tmp_pap.code = PAP_BAD_SPW;
+
+ /* Send in PAP and wait for response */
+ if ((error = send_frame(client_fd, &tmp_pap, LEN, session_key)) < 0) {
+ printf("Failed to send PAP frame\n");
+ return -1;
+ }
+ if ((error = recv_frame(client_fd, LEN, session_key, &tmp_pap)) < 0) {
+ printf("Failed to recv PAP frame\n");
+ return error;
+ }
+
+ ++attempts;
+ }
+
+ return 0;
+}
+
+int
+negotiate_spw(int client_fd, unsigned char *session_key)
+{
+ const size_t LEN = sizeof(struct pap);
+ struct pap pap;
+ int error;
+
+ /* Get PAP from the network */
+ if ((error = recv_frame(client_fd, LEN, session_key, &pap)) < 0) {
+ return error;
+ }
+
+ return handle_pap(client_fd, &pap, session_key);
+}