]> git.feebdaed.xyz Git - socialize.git/commitdiff
add: cli connect
authorseantywork <seantywork@gmail.com>
Wed, 19 Feb 2025 12:39:06 +0000 (12:39 +0000)
committerseantywork <seantywork@gmail.com>
Wed, 19 Feb 2025 12:39:06 +0000 (12:39 +0000)
.gitignore
cmd/cli/main.c
include/rat-chat/cli/cli.h
include/rat-chat/core.h
include/rat-chat/utils.h
src/cli/cli.c
src/utils.c

index 067b105f416b2e88529049d3c42ac8ce3ddec540..0774d465b2b39e813dc74f2bf75ca4193b70def8 100644 (file)
@@ -11,3 +11,4 @@
 *.mod.c
 .vscode
 *.pem
+*.txt
index b88c30f89bca7a86d028370a9f3855bcd11f61a5..80cdfd19e720546e9cd5970df5b57da23a722341 100644 (file)
@@ -1,31 +1,47 @@
 #include "rat-chat/cli/cli.h"
 #include "rat-chat/utils.h"
 
+int cli_done = 0;
 
+static void signal_handler(int sig){
+
+
+    cli_done = 1;
+
+}
 
 int main(int argc, char **argv){
 
 
+    if(argc < 2){
+        printf("feed arguments\n");
+        printf("addr, or addr + number\n");
+
+        return -1;
+    }
+
+
+    signal(SIGINT, signal_handler);
 
-    if(argc == 1){
+    if(argc == 2){
 
-        run_cli();
+        run_cli(argv[1]);
 
 
     } else {
 
-        if(strcmp(argv[1], "1") == 0){
+        if(strcmp(argv[2], "1") == 0){
 
 
-            run_cli_test(1);
+            run_cli_test(argv[1], 1);
 
-        } else if (strcmp(argv[1], "2") == 0){
+        } else if (strcmp(argv[2], "2") == 0){
 
-            run_cli_test(2);
+            run_cli_test(argv[1], 2);
 
         } else {
 
-            printf("wrong argument: %s\n", argv[1]);
+            printf("wrong argument: %s\n", argv[2]);
 
             return -1;
 
index cba6282418ab56206b0e8313a6397fd62b584fde..0abeaf8b091e831bf21f2b9db515cb52a420b678 100644 (file)
@@ -4,17 +4,43 @@
 #include "rat-chat/core.h"
 
 
+#ifndef VERIFICATION_LOCATION
+# define VERIFICATION_LOCATION "tls/ca.crt.pem"
+#endif
 
 
+# define ASSERT(x) { \
+  if(!(x)) { \
+    fprintf(stderr, "Assertion: %s: function %s, line %d\n", (char*)(__FILE__), (char*)(__func__), (int)__LINE__); \
+    exit(SIGTRAP); \
+  } \
+}
 
-void run_cli();
 
 
-void run_cli_test(int tc);
 
+void run_cli(char* addr);
 
 
+void run_cli_test(char* addr, int tc);
 
 
+int connect_to_engine(char* addr, long timeout);
+
+
+void* reader();
+
+
+
+int verify_callback(int preverify, X509_STORE_CTX* x509_ctx);
+
+void init_openssl_library(void);
+void print_cn_name(const char* label, X509_NAME* const name);
+void print_san_name(const char* label, X509* const cert);
+void print_error_string(unsigned long err, const char* const label);
+
+extern int cli_done;
+extern char* PREFERRED_CIPHERS;
+
 
 #endif 
index 4c6c1a74a8b0c562684abd76dfc558f88048b1b8..b3054ab21a22aed7ae124b285fab95b07d956a8b 100644 (file)
@@ -4,28 +4,35 @@
 
 
 #include <stdio.h> 
-#include <netdb.h> 
 #include <netinet/in.h> 
 #include <stdlib.h> 
 #include <string.h> 
 #include <stdint.h>
-#include <sys/socket.h> 
-#include <sys/types.h> 
+#include <sys/types.h>
+#include <sys/socket.h>  
 #include <unistd.h> 
 #include <time.h>
 #include <endian.h>
 #include <pthread.h>
 #include <stdarg.h>
 #include <sys/time.h>
-// ep headers
+#include <poll.h>
+#include <signal.h>
 #include <fcntl.h>
 #include <sys/epoll.h>
 #include <errno.h>
 #include <arpa/inet.h>
-// ssl headers
-#include <signal.h>
+#include <netdb.h> 
+
 #include <openssl/ssl.h>
 #include <openssl/err.h>
+#include <openssl/bio.h>
+#include <openssl/pem.h>
+#include <openssl/conf.h>
+#include <openssl/x509.h>
+#include <openssl/buffer.h>
+#include <openssl/x509v3.h>
+#include <openssl/opensslconf.h>
 
 #include "mongoose/mongoose.h"
 #include "cJSON/cJSON.h"
index f6bd1f6bd60cc3b68177de39af09cd059f0e29a0..b6fd0aa6f3e129978639d6140567f7e032725eed 100644 (file)
@@ -20,6 +20,7 @@ int bin2hex(uint8_t* hexarray, int arrlen, uint8_t* bytearray);
 
 
 
+int get_host_port(char* hostname, int* port, char* addr);
 
 
 
index 95b4af85cb110be60339f2328b34bda17edb9a3a..c46628fb02910cf40bf98cee8e08ecc47df18295 100644 (file)
 #include "rat-chat/cli/cli.h"
 #include "rat-chat/utils.h"
 
+extern char* PREFERRED_CIPHERS = "HIGH:!aNULL:!kRSA:!SRP:!PSK:!CAMELLIA:!RC4:!MD5:!DSS";
 
 
 
-void run_cli(){
+void run_cli(char* addr){
 
 
 
 }
 
 
-void run_cli_test(int tc){
+void run_cli_test(char* addr, int tc){
 
+    long res = 1;
+    int ret = 1;
+    unsigned long ssl_err = 0;
+    
+    int fd = 0;
+    SSL_METHOD *method = NULL;
+    SSL_CTX* ctx = NULL;
+    SSL *ssl = NULL;
+    
 
+    char hostname[MAX_ID_LEN] = {0};
 
+    init_openssl_library();
 
+    method = SSLv23_method();
 
+    if(method == NULL){
 
+        printf("ssl null method\n");
+
+        return -1;
+
+    }
+
+    ctx = SSL_CTX_new(method);
+
+    if(ctx == NULL){
+
+        printf("ctx null\n");
+
+        return -2;
+    }
+
+    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback);
+
+    SSL_CTX_set_verify_depth(ctx, 5);    
+
+    const long flags = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
+    
+    SSL_CTX_set_options(ctx, flags);
+
+    res = SSL_CTX_load_verify_locations(ctx, VERIFICATION_LOCATION, NULL);
+
+    if (res != 1){
+
+        printf("load verification cert\n");
+
+        return -3;
+    }
+
+    ssl = SSL_new(ctx);
+
+    if(ssl == NULL){
+
+        printf("ssl new failed\n");
+
+        return -4;
+    }
+
+    res = connect_to_engine(addr, 30);
+
+    if (res < 0){
+
+        printf("failed to connect: %d\n", res);
+
+        return -5;
+    }
+
+    fd = res;
+
+    SSL_set_fd(ssl, fd);
+
+    res = SSL_connect(ssl);
+
+    if(res != 1){
+
+        printf("failed to handshake: %d\n", res);
+
+        return -6;
+    }
+
+    X509* cert = SSL_get_peer_certificate(ssl);
+    
+    if(cert == NULL){
+
+        printf("failed to get peer cert\n");
+
+        return -7;
+    }
+    
+
+    res = SSL_get_verify_result(ssl);
+    
+    if (res != X509_V_OK){
+
+        printf("ssl peer verification failed\n");
+
+        return -8;
+    }
+
+
+    do {
+
+        sleep(1);
+
+        printf("sleeping\n");
+
+
+    } while(cli_done == 0);
+
+
+    if(NULL != ctx){
+        SSL_CTX_free(ctx);
+    }
+    
+    if(ssl != NULL){
+
+        SSL_free(ssl);
+    }
+    
+
+
+    return ret;
+}
+
+
+
+int connect_to_engine(char* addr, long timeout){
+
+    char hostname[MAX_ID_LEN] = {0};
+
+    int port = 0;
+
+    char ipaddr[32] = {0};
+
+    int result = get_host_port(hostname, &port, addr);
+
+    if(result < 0){
+
+        printf("failed to get host and port\n");
+
+        return result;
+    }
+
+    int status, valread, client_fd;
+    struct sockaddr_in serv_addr;
+
+    struct addrinfo hints;
+    struct addrinfo* rp;
+
+
+    char buffer[1024] = { 0 };
+    if ((client_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+        
+        printf("socket creation error\n");
+
+        return -1;
+    }
+
+    
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_family = AF_INET; // IPv4
+    hints.ai_socktype = SOCK_STREAM;
+
+    result = getaddrinfo(hostname, NULL, &hints, &rp);
+
+    if(result != 0){
+
+        printf("failed to get addr info\n");
+
+        return -11;
+    }
+
+    struct sockaddr_in* ipv4 = (struct sockaddr_in*)rp->ai_addr;
+
+    serv_addr.sin_family = AF_INET;
+    serv_addr.sin_port = htons(port);
+    serv_addr.sin_addr = ipv4->sin_addr;
+
+    struct timeval u_timeout;      
+    u_timeout.tv_sec = 5;
+    u_timeout.tv_usec = 0;
+    
+    if (setsockopt (client_fd, SOL_SOCKET, SO_RCVTIMEO, &u_timeout, sizeof(u_timeout)) < 0){
+
+        printf("set recv timeout\n");
+
+        return -3;
+    }
+    
+
+    if (setsockopt (client_fd, SOL_SOCKET, SO_SNDTIMEO, &u_timeout, sizeof(u_timeout)) < 0) {
+
+        printf("set send timeout\n");
+    
+        return -4;
+    }
+    
+
+    int rc = 0;
+    
+    int sockfd_flags_before;
+
+    sockfd_flags_before = fcntl(client_fd, F_GETFL,0);
+    
+    if(sockfd_flags_before < 0) {
+    
+        printf("failed to getfl\n");
+
+        return -5;
+    
+    }
+    
+    
+    if(fcntl(client_fd, F_SETFL, sockfd_flags_before | O_NONBLOCK)<0){
+
+
+        printf("failed to setfl\n");
+
+        return -6;
+    
+    } 
+
+
+    if (connect(client_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
+
+        if ((errno != EWOULDBLOCK) && (errno != EINPROGRESS)) {
+
+            rc = -11;
+
+        } else {
+            
+            struct timespec now;
+
+            clock_gettime(CLOCK_MONOTONIC_RAW, &now);
+
+            struct timespec deadline;
+
+            do{
+
+                clock_gettime(CLOCK_MONOTONIC_RAW, &deadline);
+
+                int ms_until_deadline = ((deadline.tv_sec - now.tv_sec) * 1000 + (deadline.tv_nsec - now.tv_nsec) / 1000000);
+                if(ms_until_deadline > timeout) { 
+                    rc = -10; 
+                    break; 
+                }
+                
+                struct pollfd pfds[] = { { .fd = client_fd, .events = POLLOUT } };
+                rc = poll(pfds, 1, ms_until_deadline);
+                
+                if(rc > 0) {
+                    int error = 0; 
+                    socklen_t len = sizeof(error);
+                    int retval = getsockopt(client_fd, SOL_SOCKET, SO_ERROR, &error, &len);
+                    if(retval == 0) {
+                        errno = error;
+                    }
+                    if(error != 0) {
+                        rc = -11;
+                    }
+                }
+
+            } while(rc == -11 && errno == EINTR);
+
+
+            if(rc == -10) {
+                
+                errno = ETIMEDOUT;
+                
+            }
+
+        }
+
+    } 
+
+    if(fcntl(client_fd,F_SETFL,sockfd_flags_before ) < 0) {
+
+        return -20;
+    }
+
+    return client_fd;
+}
+
+
+void* reader(){
+
+
+
+}
+
+
+
+void init_openssl_library(void)
+{
+
+    (void)SSL_library_init();
+
+    
+    SSL_load_error_strings();
+
+    CONF_modules_load(NULL, NULL, CONF_MFLAGS_IGNORE_MISSING_FILE);
+
+#if defined (OPENSSL_THREADS)
+    /* https://www.openssl.org/docs/crypto/threads.html */
+    fprintf(stdout, "Warning: thread locking is not implemented\n");
+#endif
+}
+
+void print_cn_name(const char* label, X509_NAME* const name)
+{
+    int idx = -1, success = 0;
+    unsigned char *utf8 = NULL;
+    
+    do
+    {
+        if(!name) break; /* failed */
+        
+        idx = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
+        if(!(idx > -1))  break; /* failed */
+        
+        X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, idx);
+        if(!entry) break; /* failed */
+        
+        ASN1_STRING* data = X509_NAME_ENTRY_get_data(entry);
+        if(!data) break; /* failed */
+        
+        int length = ASN1_STRING_to_UTF8(&utf8, data);
+        if(!utf8 || !(length > 0))  break; /* failed */
+        
+        fprintf(stdout, "  %s: %s\n", label, utf8);
+        success = 1;
+        
+    } while (0);
+    
+    if(utf8)
+        OPENSSL_free(utf8);
+    
+    if(!success)
+        fprintf(stdout, "  %s: <not available>\n", label);
 }
 
+void print_san_name(const char* label, X509* const cert)
+{
+    int success = 0;
+    GENERAL_NAMES* names = NULL;
+    unsigned char* utf8 = NULL;
+    
+    do
+    {
+        if(!cert) break; /* failed */
+        
+        names = X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0 );
+        if(!names) break;
+        
+        int i = 0, count = sk_GENERAL_NAME_num(names);
+        if(!count) break; /* failed */
+        
+        for( i = 0; i < count; ++i )
+        {
+            GENERAL_NAME* entry = sk_GENERAL_NAME_value(names, i);
+            if(!entry) continue;
+            
+            if(GEN_DNS == entry->type)
+            {
+                int len1 = 0, len2 = -1;
+                
+                len1 = ASN1_STRING_to_UTF8(&utf8, entry->d.dNSName);
+                if(utf8) {
+                    len2 = (int)strlen((const char*)utf8);
+                }
+                
+                if(len1 != len2) {
+                    fprintf(stderr, "  Strlen and ASN1_STRING size do not match (embedded null?): %d vs %d\n", len2, len1);
+                }
+                
+
+                if(utf8 && len1 && len2 && (len1 == len2)) {
+                    fprintf(stdout, "  %s: %s\n", label, utf8);
+                    success = 1;
+                }
+                
+                if(utf8) {
+                    OPENSSL_free(utf8), utf8 = NULL;
+                }
+            }
+            else
+            {
+                fprintf(stderr, "  Unknown GENERAL_NAME type: %d\n", entry->type);
+            }
+        }
 
+    } while (0);
+    
+    if(names)
+        GENERAL_NAMES_free(names);
+    
+    if(utf8)
+        OPENSSL_free(utf8);
+    
+    if(!success)
+        fprintf(stdout, "  %s: <not available>\n", label);
+    
+}
+
+int verify_callback(int preverify, X509_STORE_CTX* x509_ctx)
+{
+    
+    int depth = X509_STORE_CTX_get_error_depth(x509_ctx);
+    int err = X509_STORE_CTX_get_error(x509_ctx);
+    
+    X509* cert = X509_STORE_CTX_get_current_cert(x509_ctx);
+    X509_NAME* iname = cert ? X509_get_issuer_name(cert) : NULL;
+    X509_NAME* sname = cert ? X509_get_subject_name(cert) : NULL;
+    
+    fprintf(stdout, "verify_callback (depth=%d)(preverify=%d)\n", depth, preverify);
+    
+
+    print_cn_name("Issuer (cn)", iname);
+    
+
+    print_cn_name("Subject (cn)", sname);
+    
+    if(depth == 0) {
+
+        print_san_name("Subject (san)", cert);
+    }
+    
+    if(preverify == 0)
+    {
+        if(err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY)
+            fprintf(stdout, "  Error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY\n");
+        else if(err == X509_V_ERR_CERT_UNTRUSTED)
+            fprintf(stdout, "  Error = X509_V_ERR_CERT_UNTRUSTED\n");
+        else if(err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN)
+            fprintf(stdout, "  Error = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN\n");
+        else if(err == X509_V_ERR_CERT_NOT_YET_VALID)
+            fprintf(stdout, "  Error = X509_V_ERR_CERT_NOT_YET_VALID\n");
+        else if(err == X509_V_ERR_CERT_HAS_EXPIRED)
+            fprintf(stdout, "  Error = X509_V_ERR_CERT_HAS_EXPIRED\n");
+        else if(err == X509_V_OK)
+            fprintf(stdout, "  Error = X509_V_OK\n");
+        else
+            fprintf(stdout, "  Error = %d\n", err);
+    }
+
+#if !defined(NDEBUG)
+    return 1;
+#else
+    return preverify;
+#endif
+}
 
+void print_error_string(unsigned long err, const char* const label)
+{
+    const char* const str = ERR_reason_error_string(err);
+    if(str)
+        fprintf(stderr, "%s\n", str);
+    else
+        fprintf(stderr, "%s failed: %lu (0x%lx)\n", label, err, err);
+}
\ No newline at end of file
index 7670b5eca8fbcb093bf2cde872793a6969e3a042..86c74c961b5add62d42420c3beb852ba31d7caaa 100644 (file)
@@ -81,6 +81,53 @@ int bin2hex(uint8_t* hexarray, int arrlen, uint8_t* bytearray){
 }
 
 
+int get_host_port(char* hostname, int* port, char* addr){
+
+    char addr_cp[MAX_ID_LEN]  = {0};
+
+    char port_str[MAX_ID_LEN] = {0};
+
+    strcpy(addr_cp, addr);
+
+    char* delim = ":";
+    char *token;
+
+    token = strtok(addr, delim);
+
+    int idx = 0;
+
+    while(token != NULL) {
+    
+        if(idx == 0){
+
+            strcpy(hostname, token);
+
+        } else if (idx == 1){
+
+
+            strcpy(port_str, token);
+
+            sscanf(port_str, "%d", port);
+
+        } else {
+
+            return -1;
+        }
+
+        token = strtok(NULL, delim);
+
+        idx += 1;
+
+    }
+
+    if (idx < 2){
+        return -2;
+    }
+
+    return 0;
+
+}
+
 
 void get_current_time_string(char* tstr){