diff options
Diffstat (limited to 'client/main.c')
-rw-r--r-- | client/main.c | 107 |
1 files changed, 106 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; } |