]>
Commit | Line | Data |
---|---|---|
d02b48c6 RE |
1 | /* serv.cpp - Minimal ssleay server for Unix |
2 | 30.9.1996, Sampo Kellomaki <sampo@iki.fi> */ | |
3 | ||
054009a6 BM |
4 | |
5 | /* mangled to work with SSLeay-0.9.0b and OpenSSL 0.9.2b | |
6 | Simplified to be even more minimal | |
7 | 12/98 - 4/99 Wade Scholine <wades@mail.cybg.com> */ | |
8 | ||
d02b48c6 | 9 | #include <stdio.h> |
054009a6 BM |
10 | #include <unistd.h> |
11 | #include <stdlib.h> | |
d02b48c6 RE |
12 | #include <memory.h> |
13 | #include <errno.h> | |
14 | #include <sys/types.h> | |
15 | #include <sys/socket.h> | |
16 | #include <netinet/in.h> | |
17 | #include <arpa/inet.h> | |
18 | #include <netdb.h> | |
19 | ||
7ebf7674 | 20 | #include <openssl/rsa.h> /* SSLeay stuff */ |
dd3c43c5 BM |
21 | #include <openssl/crypto.h> |
22 | #include <openssl/x509.h> | |
23 | #include <openssl/pem.h> | |
24 | #include <openssl/ssl.h> | |
25 | #include <openssl/err.h> | |
d02b48c6 | 26 | |
054009a6 BM |
27 | |
28 | /* define HOME to be dir for key and cert files... */ | |
29 | #define HOME "./" | |
30 | /* Make these what you want for cert & key files */ | |
31 | #define CERTF HOME "foo-cert.pem" | |
32 | #define KEYF HOME "foo-cert.pem" | |
33 | ||
d02b48c6 RE |
34 | |
35 | #define CHK_NULL(x) if ((x)==NULL) exit (1) | |
36 | #define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); } | |
37 | #define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(2); } | |
38 | ||
39 | void main () | |
40 | { | |
41 | int err; | |
42 | int listen_sd; | |
43 | int sd; | |
44 | struct sockaddr_in sa_serv; | |
45 | struct sockaddr_in sa_cli; | |
054009a6 | 46 | size_t client_len; |
d02b48c6 RE |
47 | SSL_CTX* ctx; |
48 | SSL* ssl; | |
49 | X509* client_cert; | |
50 | char* str; | |
51 | char buf [4096]; | |
054009a6 BM |
52 | SSL_METHOD *meth; |
53 | ||
d02b48c6 RE |
54 | /* SSL preliminaries. We keep the certificate and key with the context. */ |
55 | ||
56 | SSL_load_error_strings(); | |
054009a6 | 57 | SSLeay_add_ssl_algorithms(); |
32ec4153 | 58 | meth = TLS_server_method(); |
054009a6 BM |
59 | ctx = SSL_CTX_new (meth); |
60 | if (!ctx) { | |
61 | ERR_print_errors_fp(stderr); | |
62 | exit(2); | |
63 | } | |
d02b48c6 | 64 | |
054009a6 BM |
65 | if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0) { |
66 | ERR_print_errors_fp(stderr); | |
67 | exit(3); | |
68 | } | |
69 | if (SSL_CTX_use_PrivateKey_file(ctx, KEYF, SSL_FILETYPE_PEM) <= 0) { | |
70 | ERR_print_errors_fp(stderr); | |
71 | exit(4); | |
72 | } | |
73 | ||
74 | if (!SSL_CTX_check_private_key(ctx)) { | |
75 | fprintf(stderr,"Private key does not match the certificate public key\n"); | |
76 | exit(5); | |
77 | } | |
78 | ||
d02b48c6 RE |
79 | /* ----------------------------------------------- */ |
80 | /* Prepare TCP socket for receiving connections */ | |
81 | ||
82 | listen_sd = socket (AF_INET, SOCK_STREAM, 0); CHK_ERR(listen_sd, "socket"); | |
83 | ||
16f8d4eb | 84 | memset(&sa_serv, 0, sizeof(sa_serv)); |
d02b48c6 RE |
85 | sa_serv.sin_family = AF_INET; |
86 | sa_serv.sin_addr.s_addr = INADDR_ANY; | |
87 | sa_serv.sin_port = htons (1111); /* Server Port number */ | |
88 | ||
89 | err = bind(listen_sd, (struct sockaddr*) &sa_serv, | |
90 | sizeof (sa_serv)); CHK_ERR(err, "bind"); | |
91 | ||
92 | /* Receive a TCP connection. */ | |
93 | ||
94 | err = listen (listen_sd, 5); CHK_ERR(err, "listen"); | |
95 | ||
96 | client_len = sizeof(sa_cli); | |
97 | sd = accept (listen_sd, (struct sockaddr*) &sa_cli, &client_len); | |
98 | CHK_ERR(sd, "accept"); | |
99 | close (listen_sd); | |
100 | ||
101 | printf ("Connection from %lx, port %x\n", | |
102 | sa_cli.sin_addr.s_addr, sa_cli.sin_port); | |
103 | ||
104 | /* ----------------------------------------------- */ | |
105 | /* TCP connection is ready. Do server side SSL. */ | |
106 | ||
107 | ssl = SSL_new (ctx); CHK_NULL(ssl); | |
108 | SSL_set_fd (ssl, sd); | |
109 | err = SSL_accept (ssl); CHK_SSL(err); | |
110 | ||
111 | /* Get the cipher - opt */ | |
112 | ||
113 | printf ("SSL connection using %s\n", SSL_get_cipher (ssl)); | |
114 | ||
115 | /* Get client's certificate (note: beware of dynamic allocation) - opt */ | |
116 | ||
117 | client_cert = SSL_get_peer_certificate (ssl); | |
118 | if (client_cert != NULL) { | |
119 | printf ("Client certificate:\n"); | |
120 | ||
054009a6 | 121 | str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0); |
d02b48c6 RE |
122 | CHK_NULL(str); |
123 | printf ("\t subject: %s\n", str); | |
ef0ab7f9 | 124 | OPENSSL_free (str); |
d02b48c6 | 125 | |
054009a6 | 126 | str = X509_NAME_oneline (X509_get_issuer_name (client_cert), 0, 0); |
d02b48c6 RE |
127 | CHK_NULL(str); |
128 | printf ("\t issuer: %s\n", str); | |
ef0ab7f9 | 129 | OPENSSL_free (str); |
d02b48c6 RE |
130 | |
131 | /* We could do all sorts of certificate verification stuff here before | |
132 | deallocating the certificate. */ | |
133 | ||
134 | X509_free (client_cert); | |
135 | } else | |
136 | printf ("Client does not have certificate.\n"); | |
137 | ||
138 | /* DATA EXCHANGE - Receive message and send reply. */ | |
139 | ||
140 | err = SSL_read (ssl, buf, sizeof(buf) - 1); CHK_SSL(err); | |
141 | buf[err] = '\0'; | |
142 | printf ("Got %d chars:'%s'\n", err, buf); | |
143 | ||
144 | err = SSL_write (ssl, "I hear you.", strlen("I hear you.")); CHK_SSL(err); | |
145 | ||
146 | /* Clean up. */ | |
147 | ||
148 | close (sd); | |
149 | SSL_free (ssl); | |
150 | SSL_CTX_free (ctx); | |
151 | } | |
152 | /* EOF - serv.cpp */ |