Last active
December 29, 2022 17:19
-
-
Save MartinMReed/6393150 to your computer and use it in GitHub Desktop.
OpenSSL Server, Reference Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <openssl/ssl.h> | |
#include <openssl/bio.h> | |
#include <openssl/err.h> | |
#include <string> | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
#define IP_ADDR INADDR_ANY | |
#define PORT 8081 | |
int password_cb(char *buf, int size, int rwflag, void *password); | |
EVP_PKEY *generatePrivateKey(); | |
X509 *generateCertificate(EVP_PKEY *pkey); | |
/** | |
* Example SSL server that accepts a client and echos back anything it receives. | |
* Test using `curl -I https://127.0.0.1:8081 --insecure` | |
*/ | |
int main(int arc, char **argv) | |
{ | |
int fd = socket(AF_INET, SOCK_STREAM, 0); | |
if (fd < 0) { | |
printf("opening socket\n"); | |
return -4; | |
} | |
struct sockaddr_in s_addr; | |
bzero((char *)&s_addr, sizeof(s_addr)); | |
s_addr.sin_family = AF_INET; | |
s_addr.sin_addr.s_addr = IP_ADDR; | |
s_addr.sin_port = htons(PORT); | |
if (bind(fd, (struct sockaddr*)&s_addr, sizeof(s_addr)) < 0) { | |
printf("binding\n"); | |
return -5; | |
} | |
listen(fd, 2); | |
int cfd; | |
while (cfd = accept(fd, 0, 0)) | |
{ | |
SSL_load_error_strings(); | |
ERR_load_crypto_strings(); | |
OpenSSL_add_all_algorithms(); | |
SSL_library_init(); | |
SSL_CTX *ctx = SSL_CTX_new(SSLv3_server_method()); | |
if (ctx == NULL) { | |
printf("errored; unable to load context.\n"); | |
ERR_print_errors_fp(stderr); | |
return -3; | |
} | |
EVP_PKEY *pkey = generatePrivateKey(); | |
X509 *x509 = generateCertificate(pkey); | |
SSL_CTX_use_certificate(ctx, x509); | |
SSL_CTX_set_default_passwd_cb(ctx, password_cb); | |
SSL_CTX_use_PrivateKey(ctx, pkey); | |
RSA *rsa=RSA_generate_key(512, RSA_F4, NULL, NULL); | |
SSL_CTX_set_tmp_rsa(ctx, rsa); | |
RSA_free(rsa); | |
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); | |
SSL *ssl = SSL_new(ctx); | |
BIO *accept_bio = BIO_new_socket(cfd, BIO_CLOSE); | |
SSL_set_bio(ssl, accept_bio, accept_bio); | |
SSL_accept(ssl); | |
ERR_print_errors_fp(stderr); | |
BIO *bio = BIO_pop(accept_bio); | |
char buf[1024]; | |
while (1) | |
{ | |
// first read data | |
int r = SSL_read(ssl, buf, 1024); | |
switch (SSL_get_error(ssl, r)) | |
{ | |
case SSL_ERROR_NONE: | |
break; | |
case SSL_ERROR_ZERO_RETURN: | |
goto end; | |
default: | |
printf("SSL read problem"); | |
goto end; | |
} | |
int len = r; | |
// now keep writing until we've written everything | |
int offset = 0; | |
while (len) | |
{ | |
r = SSL_write(ssl, buf + offset, len); | |
switch (SSL_get_error(ssl, r)) | |
{ | |
case SSL_ERROR_NONE: | |
len -= r; | |
offset += r; | |
break; | |
default: | |
printf("SSL write problem"); | |
goto end; | |
} | |
} | |
} | |
end: | |
SSL_shutdown(ssl); | |
BIO_free_all(bio); | |
BIO_free_all(accept_bio); | |
} | |
return 0; | |
} | |
int password_cb(char *buf, int size, int rwflag, void *password) | |
{ | |
strncpy(buf, (char *)(password), size); | |
buf[size - 1] = '\0'; | |
return strlen(buf); | |
} | |
EVP_PKEY *generatePrivateKey() | |
{ | |
EVP_PKEY *pkey = NULL; | |
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); | |
EVP_PKEY_keygen_init(pctx); | |
EVP_PKEY_CTX_set_rsa_keygen_bits(pctx, 2048); | |
EVP_PKEY_keygen(pctx, &pkey); | |
return pkey; | |
} | |
X509 *generateCertificate(EVP_PKEY *pkey) | |
{ | |
X509 *x509 = X509_new(); | |
X509_set_version(x509, 2); | |
ASN1_INTEGER_set(X509_get_serialNumber(x509), 0); | |
X509_gmtime_adj(X509_get_notBefore(x509), 0); | |
X509_gmtime_adj(X509_get_notAfter(x509), (long)60*60*24*365); | |
X509_set_pubkey(x509, pkey); | |
X509_NAME *name = X509_get_subject_name(x509); | |
X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (const unsigned char*)"US", -1, -1, 0); | |
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (const unsigned char*)"YourCN", -1, -1, 0); | |
X509_set_issuer_name(x509, name); | |
X509_sign(x509, pkey, EVP_md5()); | |
return x509; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment