Initial https proxy work
The proxy can now sit between a client and a https web server. It does this by looking for a CONNECT request that conventional proxies use to open a tunnel between a client and an https server. Instead of opening an opaque tunnel, yaip immediately sends bacck a "connection established" response. This tells the client (browser normally) to proceed and initiate an HTTPS connection. I use the host that was send in the connect request to set up a fake SSL server. If we have seen the domain before, we re-use the certificate, otherwise we generate a new one and sign it using YAIP's built in certificate authority. I still need to do work on forwarding the request upstream. This is my next job. Currently, yaip responds with a valid response of "it worked". ``` $ curl https://example.com --cacert ~/.config/yaip/cert.pem It worked ``` Notice, we don't get any certificate errors because we are telling curl to trust the authority that yaip uses
This commit is contained in:
		
							parent
							
								
									1beca38af6
								
							
						
					
					
						commit
						dd71d26245
					
				
					 15 changed files with 330 additions and 109 deletions
				
			
		
							
								
								
									
										10
									
								
								src/main.c
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								src/main.c
									
										
									
									
									
								
							| 
						 | 
					@ -68,7 +68,10 @@ int startListener(unsigned int port){
 | 
				
			||||||
int main(int argc, char**argv){
 | 
					int main(int argc, char**argv){
 | 
				
			||||||
	Config *config = configDefaults();
 | 
						Config *config = configDefaults();
 | 
				
			||||||
	int listener;
 | 
						int listener;
 | 
				
			||||||
	CertList *certs = NULL;
 | 
						CertificateAutority *ca = malloc( sizeof( CertificateAutority ) );
 | 
				
			||||||
 | 
						ca->cert = NULL;
 | 
				
			||||||
 | 
						ca->pkey = NULL;
 | 
				
			||||||
 | 
						ca->certs = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for ( unsigned int i = 1; i < argc; i++ ){
 | 
						for ( unsigned int i = 1; i < argc; i++ ){
 | 
				
			||||||
| 
						 | 
					@ -112,6 +115,7 @@ int main(int argc, char**argv){
 | 
				
			||||||
			return 1;
 | 
								return 1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						ca->pkey = read_private_key( config->keyfile );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!path_exists( config->certfile ) ){
 | 
						if (!path_exists( config->certfile ) ){
 | 
				
			||||||
		printf("Creating cert\n");
 | 
							printf("Creating cert\n");
 | 
				
			||||||
| 
						 | 
					@ -119,6 +123,7 @@ int main(int argc, char**argv){
 | 
				
			||||||
			return 1;
 | 
								return 1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						ca->cert = read_cert( config->certfile );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	listener = startListener(config->port);
 | 
						listener = startListener(config->port);
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
| 
						 | 
					@ -151,12 +156,11 @@ int main(int argc, char**argv){
 | 
				
			||||||
			// necesarily the hosts header
 | 
								// necesarily the hosts header
 | 
				
			||||||
			webserverRequest(request, client);
 | 
								webserverRequest(request, client);
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			proxyRequest(request, client, certs);
 | 
								proxyRequest(request, client, ca);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
		close(client);
 | 
							close(client);
 | 
				
			||||||
		freeRequest( request );
 | 
							freeRequest( request );
 | 
				
			||||||
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										90
									
								
								src/proxy.c
									
										
									
									
									
								
							
							
						
						
									
										90
									
								
								src/proxy.c
									
										
									
									
									
								
							| 
						 | 
					@ -16,7 +16,7 @@ Response *upstreamGetResponse(Request *request){
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	address.sin_family = AF_INET;
 | 
						address.sin_family = AF_INET;
 | 
				
			||||||
	address.sin_port = htons( 80 );
 | 
						address.sin_port = htons( request->port );
 | 
				
			||||||
	// We want the request to go out to whatever the host was resolved to
 | 
						// We want the request to go out to whatever the host was resolved to
 | 
				
			||||||
	memcpy( &address.sin_addr, host->h_addr_list[0], host->h_length );
 | 
						memcpy( &address.sin_addr, host->h_addr_list[0], host->h_length );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,47 +35,77 @@ Response *upstreamGetResponse(Request *request){
 | 
				
			||||||
	rsp = newResponseFromSocket( client_fd );
 | 
						rsp = newResponseFromSocket( client_fd );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return rsp;
 | 
						return rsp;
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void proxyRequest(Request *request, int client, CertList *certs){
 | 
					void sendConnectionEstablished(int client){
 | 
				
			||||||
 | 
						// If it is a connect request, we are dealing with https
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// I am basically doing the same thing that mitmproxy does here
 | 
				
			||||||
 | 
						// We start by responding with 200 Connection Established which
 | 
				
			||||||
 | 
						// in a normal proxy would mean that we have established a
 | 
				
			||||||
 | 
						// connection with the remote host. However, we haven't because we
 | 
				
			||||||
 | 
						// are going to pretend to be the host to the client and pretend to
 | 
				
			||||||
 | 
						// be the client to the host
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Response *response = newResponse();
 | 
				
			||||||
 | 
						connectionEstablished(response);
 | 
				
			||||||
 | 
						char *responseStr = responseToString(response);
 | 
				
			||||||
 | 
						send(client , responseStr, strlen(responseStr) , 0 );
 | 
				
			||||||
 | 
						freeResponse( response );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void proxyRequest(Request *request, int client, CertificateAutority *ca){
 | 
				
			||||||
	if ( strcmp( request->method, "CONNECT" ) == 0 ){
 | 
						if ( strcmp( request->method, "CONNECT" ) == 0 ){
 | 
				
			||||||
		// If it is a connect request, we are dealing with https
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// I am basically doing the same thing that mitmproxy does here
 | 
							sendConnectionEstablished(client);
 | 
				
			||||||
		// We start by responding with 200 Connection Established which
 | 
					 | 
				
			||||||
		// in a normal proxy would mean that we have established a
 | 
					 | 
				
			||||||
		// connection with the remote host. However, we haven't because we
 | 
					 | 
				
			||||||
		// are going to pretend to be the host to the client and pretend to
 | 
					 | 
				
			||||||
		// be the client to the host
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Response *response = newResponse();
 | 
							// All we might need from the connect resquest is the host
 | 
				
			||||||
		connectionEstablished(response);
 | 
							char *host = request->host;
 | 
				
			||||||
		char *responseStr = responseToString(response);
 | 
							freeRequest( request );
 | 
				
			||||||
		send(client , responseStr, strlen(responseStr) , 0 );
 | 
					
 | 
				
			||||||
 | 
							// If we already have a host cert for the domain we're dealing with use
 | 
				
			||||||
 | 
							// it
 | 
				
			||||||
 | 
							CertList *certItem = findCertListItem( ca->certs, host );
 | 
				
			||||||
 | 
							if ( certItem == NULL ){
 | 
				
			||||||
 | 
								// If we don't, generate a new one
 | 
				
			||||||
 | 
								X509 *siteCert = generate_site_cert( ca->pkey, ca->cert, host );
 | 
				
			||||||
 | 
								certItem = newCertListItem( host, ca->pkey, siteCert );
 | 
				
			||||||
 | 
								if ( ca->certs == NULL ) ca->certs = certItem;
 | 
				
			||||||
 | 
								else getLastCertListItem(ca->certs)->next = certItem;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							SSL_CTX *ctx;
 | 
				
			||||||
 | 
							SSL *ssl;
 | 
				
			||||||
 | 
							char buf[1024] = {0};
 | 
				
			||||||
 | 
							int bytes;
 | 
				
			||||||
 | 
							Response *response;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							SSL_library_init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ctx = setup_ctx(certItem);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		//SSL_CTX *ctx;
 | 
							ssl = SSL_new(ctx);
 | 
				
			||||||
		//SSL *ssl;
 | 
							SSL_set_fd( ssl, client );
 | 
				
			||||||
		//char buf[1024] = {0};
 | 
					 | 
				
			||||||
		//int bytes;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		//SSL_library_init();
 | 
							if ( SSL_accept(ssl) == -1 ){
 | 
				
			||||||
		//ctx = InitServerCTX(config);
 | 
								ERR_print_errors_fp(stderr);
 | 
				
			||||||
		//ssl = SSL_new(ctx);
 | 
							} else {
 | 
				
			||||||
		//SSL_set_fd( ssl, client );
 | 
								bytes = SSL_read(ssl, buf, sizeof(buf));
 | 
				
			||||||
 | 
								buf[bytes] = '\0';
 | 
				
			||||||
		//if ( SSL_accept(ssl) == -1 ){
 | 
								request = newRequestFromString( buf );
 | 
				
			||||||
		//	ERR_print_errors_fp(stderr);
 | 
								//If this request doesn't contain a host, use the one from the
 | 
				
			||||||
		//} else {
 | 
								//connect request
 | 
				
			||||||
		//	bytes = SSL_read(ssl, buf, sizeof(buf));
 | 
								if ( strlen( request->host ) == 0 ){
 | 
				
			||||||
		//	buf[bytes] = '\0';
 | 
									free(request->host);
 | 
				
			||||||
		//	printf("%s", buf);
 | 
									request->host = strdup( host );
 | 
				
			||||||
		//}
 | 
								}
 | 
				
			||||||
 | 
								response = upstreamGetResponse(request);
 | 
				
			||||||
 | 
								char *responseStr = responseToString( response );
 | 
				
			||||||
 | 
								SSL_write( ssl, responseStr, strlen(responseStr) );
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							SSL_free(ssl);
 | 
				
			||||||
 | 
							SSL_CTX_free(ctx);
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		Response *response = upstreamGetResponse(request);
 | 
							Response *response = upstreamGetResponse(request);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,9 @@
 | 
				
			||||||
#include "ssl.h"
 | 
					#include "ssl.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Response *upstreamGetResponse(Request *request);
 | 
					Response *upstreamGetResponse(Request *request);
 | 
				
			||||||
 | 
					void sendConnectionEstablished(int client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void proxyRequest(Request *request, int client, CertificateAutority *ca);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void proxyRequest(Request *request, int client, CertList *certs);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* ifndef PROXY_H */
 | 
					#endif /* ifndef PROXY_H */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,50 +0,0 @@
 | 
				
			||||||
// https://man7.org/tlpi/code/online/dist/sockets/read_line.c.html
 | 
					 | 
				
			||||||
#include "readline.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Read characters from 'fd' until a newline is encountered. If a newline
 | 
					 | 
				
			||||||
  character is not encountered in the first (n - 1) bytes, then the excess
 | 
					 | 
				
			||||||
  characters are discarded. The returned string placed in 'buf' is
 | 
					 | 
				
			||||||
  null-terminated and includes the newline character if it was read in the
 | 
					 | 
				
			||||||
  first (n - 1) bytes. The function return value is the number of bytes
 | 
					 | 
				
			||||||
  placed in buffer (which includes the newline character if encountered,
 | 
					 | 
				
			||||||
  but excludes the terminating null byte). */
 | 
					 | 
				
			||||||
ssize_t fdReadLine(int fd, void *buffer, size_t n) {
 | 
					 | 
				
			||||||
    ssize_t numRead;                    /* # of bytes fetched by last read() */
 | 
					 | 
				
			||||||
    size_t totRead;                     /* Total bytes read so far */
 | 
					 | 
				
			||||||
    char *buf;
 | 
					 | 
				
			||||||
    char ch;
 | 
					 | 
				
			||||||
    if (n <= 0 || buffer == NULL) {
 | 
					 | 
				
			||||||
        errno = EINVAL;
 | 
					 | 
				
			||||||
        return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    buf = buffer;                       /* No pointer arithmetic on "void *" */
 | 
					 | 
				
			||||||
    totRead = 0;
 | 
					 | 
				
			||||||
    for (;;) {
 | 
					 | 
				
			||||||
        numRead = read(fd, &ch, 1);
 | 
					 | 
				
			||||||
        if (numRead == -1) {
 | 
					 | 
				
			||||||
            if (errno == EINTR)         /* Interrupted --> restart read() */
 | 
					 | 
				
			||||||
                continue;
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
                return -1;              /* Some other error */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        } else if (numRead == 0) {      /* EOF */
 | 
					 | 
				
			||||||
            if (totRead == 0)           /* No bytes read; return 0 */
 | 
					 | 
				
			||||||
                return 0;
 | 
					 | 
				
			||||||
            else                        /* Some bytes read; add '\0' */
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        } else {                        /* 'numRead' must be 1 if we get here */
 | 
					 | 
				
			||||||
            if (totRead < n - 1) {      /* Discard > (n - 1) bytes */
 | 
					 | 
				
			||||||
                totRead++;
 | 
					 | 
				
			||||||
                *buf++ = ch;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (ch == '\n')
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    *buf = '\0';
 | 
					 | 
				
			||||||
    return totRead;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,9 +0,0 @@
 | 
				
			||||||
#ifndef READLINE_H
 | 
					 | 
				
			||||||
#define READLINE_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <unistd.h>
 | 
					 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ssize_t fdReadLine(int fd, void *buffer, size_t n);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif /* ifndef READLINE_H */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -83,6 +83,7 @@ void requestFirstLine( Request *req, char line[] ){
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ( strlen(req->protocol) == 0 ){
 | 
						if ( strlen(req->protocol) == 0 ){
 | 
				
			||||||
 | 
							free(req->protocol);
 | 
				
			||||||
		if ( req->port == 443 )
 | 
							if ( req->port == 443 )
 | 
				
			||||||
			req->protocol = strdup("https");
 | 
								req->protocol = strdup("https");
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
| 
						 | 
					@ -122,6 +123,39 @@ Request* newRequestFromSocket(int socket){
 | 
				
			||||||
	return req;
 | 
						return req;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Request* newRequestFromString(char *string){
 | 
				
			||||||
 | 
						// We don't want to modify the original string
 | 
				
			||||||
 | 
						char *str = strdup(string);
 | 
				
			||||||
 | 
						Request *req = newRequest();
 | 
				
			||||||
 | 
						int valread;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//Find the new line
 | 
				
			||||||
 | 
						char *occurance = strchr( str, '\n' );
 | 
				
			||||||
 | 
						occurance[0] = '\0';
 | 
				
			||||||
 | 
						requestFirstLine(req, str);
 | 
				
			||||||
 | 
						str = occurance + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						occurance = strchr( str, '\n' );
 | 
				
			||||||
 | 
						occurance[0] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while ( strlen(str) > 1 ){
 | 
				
			||||||
 | 
							requestAddHeader( req, str );
 | 
				
			||||||
 | 
							str = occurance + 1;
 | 
				
			||||||
 | 
							occurance = strchr( str, '\n' );
 | 
				
			||||||
 | 
							occurance[0] = '\0';
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//TODO: make requests work with a body
 | 
				
			||||||
 | 
						//contentLength = getHeader( req->headers, "content-length" );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//if ( contentLength != NULL ){
 | 
				
			||||||
 | 
						//	printf( "Content length is %i\n", atoi(contentLength->value) );
 | 
				
			||||||
 | 
						//}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						return req;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
char* requestToString( Request *req){
 | 
					char* requestToString( Request *req){
 | 
				
			||||||
	unsigned int fullLength = strlen(req->method) + 1 + sizeof( req->path ) +
 | 
						unsigned int fullLength = strlen(req->method) + 1 + sizeof( req->path ) +
 | 
				
			||||||
		//11 = [space]http/1.1\r\n
 | 
							//11 = [space]http/1.1\r\n
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,10 +7,9 @@
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <netinet/in.h>
 | 
					#include <netinet/in.h>
 | 
				
			||||||
#include <math.h>
 | 
					#include <math.h>
 | 
				
			||||||
#include "readline.h"
 | 
					 | 
				
			||||||
#include "requestresponse.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "./util.h"
 | 
					#include "util.h"
 | 
				
			||||||
 | 
					#include "requestresponse.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,6 +32,7 @@ typedef struct {
 | 
				
			||||||
Request* newRequest();
 | 
					Request* newRequest();
 | 
				
			||||||
void requestFirstLine( Request *req, char line[] );
 | 
					void requestFirstLine( Request *req, char line[] );
 | 
				
			||||||
Request* newRequestFromSocket(int socket);
 | 
					Request* newRequestFromSocket(int socket);
 | 
				
			||||||
 | 
					Request* newRequestFromString(char *string);
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
* requestToString
 | 
					* requestToString
 | 
				
			||||||
* @prarm req the request to convert
 | 
					* @prarm req the request to convert
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,6 +50,10 @@ void responseSetBody(Response *rsp, char *string, bool updateContentLength){
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ( updateContentLength ){
 | 
						if ( updateContentLength ){
 | 
				
			||||||
		Header *contentLengthHeader = getHeader(rsp->headers, "content-length");
 | 
							Header *contentLengthHeader = getHeader(rsp->headers, "content-length");
 | 
				
			||||||
 | 
							if ( contentLengthHeader == NULL ){
 | 
				
			||||||
 | 
								responseAddHeader( rsp, "content-length: 0" );
 | 
				
			||||||
 | 
								contentLengthHeader = getHeader(rsp->headers, "content-length");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		char *value = malloc(sizeof(char) * 20);
 | 
							char *value = malloc(sizeof(char) * 20);
 | 
				
			||||||
		sprintf(value, "%lu", strlen(string) );
 | 
							sprintf(value, "%lu", strlen(string) );
 | 
				
			||||||
		contentLengthHeader->value = strdup(value);
 | 
							contentLengthHeader->value = strdup(value);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,7 @@
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <stdbool.h>
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "readline.h"
 | 
					#include "util.h"
 | 
				
			||||||
#include "requestresponse.h"
 | 
					#include "requestresponse.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										41
									
								
								src/ssl.c
									
										
									
									
									
								
							
							
						
						
									
										41
									
								
								src/ssl.c
									
										
									
									
									
								
							| 
						 | 
					@ -1,13 +1,14 @@
 | 
				
			||||||
#include "ssl.h"
 | 
					#include "ssl.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SSL_CTX* setup_ctx(CertList *certItem) {
 | 
				
			||||||
SSL_CTX* InitServerCTX(Config *config) {
 | 
					 | 
				
			||||||
	const SSL_METHOD *method;
 | 
						const SSL_METHOD *method;
 | 
				
			||||||
	SSL_CTX *ctx;
 | 
						SSL_CTX *ctx;
 | 
				
			||||||
	OpenSSL_add_all_algorithms();  /* load & register all cryptos, etc. */
 | 
						OpenSSL_add_all_algorithms();  /* load & register all cryptos, etc. */
 | 
				
			||||||
	SSL_load_error_strings();   /* load all error messages */
 | 
						SSL_load_error_strings();   /* load all error messages */
 | 
				
			||||||
	method = TLS_server_method();  /* create new server-method instance */
 | 
						method = TLS_server_method();  /* create new server-method instance */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx = SSL_CTX_new(method);   /* create new context from method */
 | 
						ctx = SSL_CTX_new(method);   /* create new context from method */
 | 
				
			||||||
	if ( ctx == NULL ) {
 | 
						if ( ctx == NULL ) {
 | 
				
			||||||
		ERR_print_errors_fp(stderr);
 | 
							ERR_print_errors_fp(stderr);
 | 
				
			||||||
| 
						 | 
					@ -15,18 +16,18 @@ SSL_CTX* InitServerCTX(Config *config) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//set the local certificate from CertFile
 | 
						//set the local certificate from CertFile
 | 
				
			||||||
	if ( SSL_CTX_use_certificate_file(ctx, config->certfile, SSL_FILETYPE_PEM) <= 0 ){
 | 
						if ( SSL_CTX_use_certificate(ctx, certItem->cert) <= 0 ){
 | 
				
			||||||
		ERR_print_errors_fp(stderr);
 | 
							ERR_print_errors_fp(stderr);
 | 
				
			||||||
		abort();
 | 
							abort();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	//set the private key from KeyFile (may be the same as CertFile)
 | 
						//set the private key from KeyFile (may be the same as CertFile)
 | 
				
			||||||
	if ( SSL_CTX_use_PrivateKey_file(ctx, config->keyfile, SSL_FILETYPE_PEM) <= 0 ){
 | 
						if ( SSL_CTX_use_PrivateKey(ctx, certItem->key) <= 0 ){
 | 
				
			||||||
		ERR_print_errors_fp(stderr);
 | 
							ERR_print_errors_fp(stderr);
 | 
				
			||||||
		abort();
 | 
							abort();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	//verify private key
 | 
						//verify private key
 | 
				
			||||||
    if ( !SSL_CTX_check_private_key(ctx) ) {
 | 
						if ( !SSL_CTX_check_private_key(ctx) ) {
 | 
				
			||||||
		fprintf(stderr, "Private key does not match the public certificate\n");
 | 
							fprintf(stderr, "Private key does not match the public certificate\n");
 | 
				
			||||||
		abort();
 | 
							abort();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -35,6 +36,7 @@ SSL_CTX* InitServerCTX(Config *config) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Generates a 2048-bit RSA key.
 | 
					// Generates a 2048-bit RSA key.
 | 
				
			||||||
// Largely stolen from here: https://gist.github.com/nathan-osman/5041136
 | 
					// Largely stolen from here: https://gist.github.com/nathan-osman/5041136
 | 
				
			||||||
EVP_PKEY* generate_ca_key() {
 | 
					EVP_PKEY* generate_ca_key() {
 | 
				
			||||||
| 
						 | 
					@ -60,7 +62,6 @@ EVP_PKEY* generate_ca_key() {
 | 
				
			||||||
    return pkey;
 | 
					    return pkey;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
// Generates a self-signed x509 certificate.
 | 
					// Generates a self-signed x509 certificate.
 | 
				
			||||||
// Largely stolen from here: https://gist.github.com/nathan-osman/5041136
 | 
					// Largely stolen from here: https://gist.github.com/nathan-osman/5041136
 | 
				
			||||||
X509* generate_ca_cert(EVP_PKEY * pkey) {
 | 
					X509* generate_ca_cert(EVP_PKEY * pkey) {
 | 
				
			||||||
| 
						 | 
					@ -177,7 +178,6 @@ bool create_and_save_key(char keyfile[]) {
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
bool create_and_save_cert(char certfile[], EVP_PKEY *pkey) {
 | 
					bool create_and_save_cert(char certfile[], EVP_PKEY *pkey) {
 | 
				
			||||||
    // Open the PEM file for writing the certificate to disk.
 | 
					    // Open the PEM file for writing the certificate to disk.
 | 
				
			||||||
    FILE * x509_file = fopen(certfile, "wb");
 | 
					    FILE * x509_file = fopen(certfile, "wb");
 | 
				
			||||||
| 
						 | 
					@ -204,7 +204,6 @@ bool create_and_save_cert(char certfile[], EVP_PKEY *pkey) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EVP_PKEY* read_private_key(char keyfile[]){
 | 
					EVP_PKEY* read_private_key(char keyfile[]){
 | 
				
			||||||
 | 
					 | 
				
			||||||
	FILE *fp;
 | 
						FILE *fp;
 | 
				
			||||||
	EVP_PKEY *pkey;
 | 
						EVP_PKEY *pkey;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -218,10 +217,30 @@ EVP_PKEY* read_private_key(char keyfile[]){
 | 
				
			||||||
	if ( pkey == NULL ){
 | 
						if ( pkey == NULL ){
 | 
				
			||||||
		perror("Error cant read certificate private key file.\n");
 | 
							perror("Error cant read certificate private key file.\n");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						fclose(fp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return pkey;
 | 
						return pkey;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					X509* read_cert(char certfile[]){
 | 
				
			||||||
 | 
						FILE *fp;
 | 
				
			||||||
 | 
						X509 *cert;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (! (fp = fopen(certfile, "r"))){
 | 
				
			||||||
 | 
							perror("Error cant open certificate private key file.\n");
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cert = PEM_read_X509( fp, NULL, NULL, NULL );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( cert == NULL ){
 | 
				
			||||||
 | 
							perror("Error cant read certificate private key file.\n");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						fclose(fp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cert;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CertList *newCertListItem(char *host, EVP_PKEY *key, X509 *cert){
 | 
					CertList *newCertListItem(char *host, EVP_PKEY *key, X509 *cert){
 | 
				
			||||||
	CertList *item = malloc(sizeof( CertList ));
 | 
						CertList *item = malloc(sizeof( CertList ));
 | 
				
			||||||
	item->host = host;
 | 
						item->host = host;
 | 
				
			||||||
| 
						 | 
					@ -245,3 +264,9 @@ unsigned int countCertListItems(CertList *item){
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return count;
 | 
						return count;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CertList *findCertListItem( CertList *item, char *host ){
 | 
				
			||||||
 | 
						while ( item != NULL && strcmp( host, item->host ) != 0 ) item = item->next;
 | 
				
			||||||
 | 
						return item;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										85
									
								
								src/ssl.h
									
										
									
									
									
								
							
							
						
						
									
										85
									
								
								src/ssl.h
									
										
									
									
									
								
							| 
						 | 
					@ -18,18 +18,97 @@ struct CertList {
 | 
				
			||||||
	CertList *next;
 | 
						CertList *next;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SSL_CTX* InitServerCTX(Config *config);
 | 
					typedef struct {
 | 
				
			||||||
 | 
						X509 *cert;
 | 
				
			||||||
 | 
						EVP_PKEY *pkey;
 | 
				
			||||||
 | 
						CertList *certs;
 | 
				
			||||||
 | 
					} CertificateAutority;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SSL_CTX* setup_ctx(CertList *certItem);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					* generate_ca_key
 | 
				
			||||||
 | 
					* Genreates a EVP_PKEY for the certificate authority
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
EVP_PKEY* generate_ca_key();
 | 
					EVP_PKEY* generate_ca_key();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					* generate_ca_cert
 | 
				
			||||||
 | 
					* Genreates a x509 cert for the certificate authority
 | 
				
			||||||
 | 
					* @param EVP_PKEY pkey - the pkey for the ca
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
X509* generate_ca_cert(EVP_PKEY * pkey);
 | 
					X509* generate_ca_cert(EVP_PKEY * pkey);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					* generate_site_cert
 | 
				
			||||||
 | 
					* Genreates a signed x509 cert for the host authority
 | 
				
			||||||
 | 
					* @param EVP_PKEY pkey - the pkey for the ca
 | 
				
			||||||
 | 
					* @param X509 caCert - the cert for the ca
 | 
				
			||||||
 | 
					* @param char* host - the common name for the certificate
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
X509* generate_site_cert( EVP_PKEY *pkey, X509 *caCert, char *host );
 | 
					X509* generate_site_cert( EVP_PKEY *pkey, X509 *caCert, char *host );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					* create_and_save_key
 | 
				
			||||||
 | 
					* Genreates a EVP_PKEY for the CA and saves it
 | 
				
			||||||
 | 
					* @param char[] keyfile - the name of the file
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
bool create_and_save_key(char keyfile[]);
 | 
					bool create_and_save_key(char keyfile[]);
 | 
				
			||||||
bool create_and_save_cert(char keyfile[], EVP_PKEY *pkey);
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					* create_and_save_cert
 | 
				
			||||||
 | 
					* Genreates a cert for the CA and saves it
 | 
				
			||||||
 | 
					* @param char[] certfile - the name of the file
 | 
				
			||||||
 | 
					* @param EVP_PKEY pkey - the pkey for the ca
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					bool create_and_save_cert(char certfile[], EVP_PKEY *pkey);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					* read_private_key
 | 
				
			||||||
 | 
					* Reades a priveate key from the keyfile
 | 
				
			||||||
 | 
					* @param char[] keyfile - the name of the file
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
EVP_PKEY* read_private_key(char keyfile[]);
 | 
					EVP_PKEY* read_private_key(char keyfile[]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					* read_cert
 | 
				
			||||||
 | 
					* Reades a cert from the certfile
 | 
				
			||||||
 | 
					* @param char[] certfile - the name of the file
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					X509* read_cert(char certfile[]);
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					* newCertListItem
 | 
				
			||||||
 | 
					* Creates an element of the CertList linked list
 | 
				
			||||||
 | 
					* @param char* host - the common name for the certificate
 | 
				
			||||||
 | 
					* @param EVP_PKEY key - the pkey
 | 
				
			||||||
 | 
					* @param X509 cert - the cert
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
CertList *newCertListItem(char *host, EVP_PKEY *key, X509 *cert);
 | 
					CertList *newCertListItem(char *host, EVP_PKEY *key, X509 *cert);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					* getLastCertListItem
 | 
				
			||||||
 | 
					* Gets the last element in the linked list
 | 
				
			||||||
 | 
					* @param CertList item - An item in the linked list
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
CertList *getLastCertListItem(CertList *item);
 | 
					CertList *getLastCertListItem(CertList *item);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					* countCertListItems
 | 
				
			||||||
 | 
					* counts the elements in the linked list
 | 
				
			||||||
 | 
					* @param CertList item - the first item in the linked list
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
unsigned int countCertListItems(CertList *item);
 | 
					unsigned int countCertListItems(CertList *item);
 | 
				
			||||||
CertList *findCertListItem( CertList *first, char *hostname );
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					* countCertListItems
 | 
				
			||||||
 | 
					* Returns the certList item with the specified host
 | 
				
			||||||
 | 
					* @param CertList item - the first item in the linked list
 | 
				
			||||||
 | 
					* @param char* host - the host we are looking for
 | 
				
			||||||
 | 
					* returns null if not there
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					CertList *findCertListItem( CertList *item, char *host );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* ifndef SSL_ */
 | 
					#endif /* ifndef SSL_ */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										48
									
								
								src/util.c
									
										
									
									
									
								
							
							
						
						
									
										48
									
								
								src/util.c
									
										
									
									
									
								
							| 
						 | 
					@ -24,3 +24,51 @@ int countLines(char fileName[]){
 | 
				
			||||||
	fclose(fp);
 | 
						fclose(fp);
 | 
				
			||||||
	return linesCount;
 | 
						return linesCount;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Read characters from 'fd' until a newline is encountered. If a newline
 | 
				
			||||||
 | 
					  character is not encountered in the first (n - 1) bytes, then the excess
 | 
				
			||||||
 | 
					  characters are discarded. The returned string placed in 'buf' is
 | 
				
			||||||
 | 
					  null-terminated and includes the newline character if it was read in the
 | 
				
			||||||
 | 
					  first (n - 1) bytes. The function return value is the number of bytes
 | 
				
			||||||
 | 
					  placed in buffer (which includes the newline character if encountered,
 | 
				
			||||||
 | 
					  but excludes the terminating null byte). */
 | 
				
			||||||
 | 
					ssize_t fdReadLine(int fd, void *buffer, size_t n) {
 | 
				
			||||||
 | 
						ssize_t numRead;                    /* # of bytes fetched by last read() */
 | 
				
			||||||
 | 
						size_t totRead;                     /* Total bytes read so far */
 | 
				
			||||||
 | 
						char *buf;
 | 
				
			||||||
 | 
						char ch;
 | 
				
			||||||
 | 
						if (n <= 0 || buffer == NULL) {
 | 
				
			||||||
 | 
							errno = EINVAL;
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						buf = buffer;                       /* No pointer arithmetic on "void *" */
 | 
				
			||||||
 | 
						totRead = 0;
 | 
				
			||||||
 | 
						for (;;) {
 | 
				
			||||||
 | 
							numRead = read(fd, &ch, 1);
 | 
				
			||||||
 | 
							if (numRead == -1) {
 | 
				
			||||||
 | 
								if (errno == EINTR)         /* Interrupted --> restart read() */
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
								return -1;              /* Some other error */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							} else if (numRead == 0) {      /* EOF */
 | 
				
			||||||
 | 
								if (totRead == 0)           /* No bytes read; return 0 */
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
								else                        /* Some bytes read; add '\0' */
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							} else {                        /* 'numRead' must be 1 if we get here */
 | 
				
			||||||
 | 
								if (totRead < n - 1) {      /* Discard > (n - 1) bytes */
 | 
				
			||||||
 | 
									totRead++;
 | 
				
			||||||
 | 
									*buf++ = ch;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (ch == '\n')
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*buf = '\0';
 | 
				
			||||||
 | 
						return totRead;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,8 +3,11 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int strpos(char *haystack, char *needle);
 | 
					int strpos(char *haystack, char *needle);
 | 
				
			||||||
int countLines(char fileName[]);
 | 
					int countLines(char fileName[]);
 | 
				
			||||||
 | 
					ssize_t fdReadLine(int fd, void *buffer, size_t n);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "munit/munit.h"
 | 
					#include "munit/munit.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "../src/readline.h"
 | 
					#include "../src/util.h"
 | 
				
			||||||
#include "../src/request.h"
 | 
					#include "../src/request.h"
 | 
				
			||||||
#include "../src/requestresponse.h"
 | 
					#include "../src/requestresponse.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -160,6 +160,18 @@ MunitResult testRequestToString(const MunitParameter params[],
 | 
				
			||||||
	return MUNIT_OK;
 | 
						return MUNIT_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MunitResult testRequestFromString(const MunitParameter params[],
 | 
				
			||||||
 | 
							void* user_data_or_fixture){
 | 
				
			||||||
 | 
						char testString[] = "GET / HTTP/1.1\r\nHost: example.com\r\nAccept: */*\r\n\r\n";
 | 
				
			||||||
 | 
						Request *req = newRequestFromString(testString);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						munit_assert_string_equal( req->method, "GET" );
 | 
				
			||||||
 | 
						munit_assert_string_equal( req->path, "/" );
 | 
				
			||||||
 | 
						munit_assert_string_equal( requestToString( req ), testString );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return MUNIT_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MunitParameterEnum test_first_line_params[2] = {NULL, NULL};
 | 
					MunitParameterEnum test_first_line_params[2] = {NULL, NULL};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static MunitTest request_tests[] = {
 | 
					static MunitTest request_tests[] = {
 | 
				
			||||||
| 
						 | 
					@ -226,6 +238,13 @@ static MunitTest request_tests[] = {
 | 
				
			||||||
		NULL, /* tear_down */
 | 
							NULL, /* tear_down */
 | 
				
			||||||
		MUNIT_TEST_OPTION_NONE, /* options */
 | 
							MUNIT_TEST_OPTION_NONE, /* options */
 | 
				
			||||||
		NULL /* parameters */
 | 
							NULL /* parameters */
 | 
				
			||||||
 | 
						},{
 | 
				
			||||||
 | 
							"/fromstring", /* name */
 | 
				
			||||||
 | 
							testRequestFromString, /* test */
 | 
				
			||||||
 | 
							NULL, /* setup */
 | 
				
			||||||
 | 
							NULL, /* tear_down */
 | 
				
			||||||
 | 
							MUNIT_TEST_OPTION_NONE, /* options */
 | 
				
			||||||
 | 
							NULL /* parameters */
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
/* Mark the end of the array with an entry where the test
 | 
					/* Mark the end of the array with an entry where the test
 | 
				
			||||||
* function is NULL */
 | 
					* function is NULL */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -145,6 +145,37 @@ MunitResult testNewHostCertificate(const MunitParameter params[],
 | 
				
			||||||
	return MUNIT_OK;
 | 
						return MUNIT_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MunitResult testFindCertListItem(const MunitParameter params[],
 | 
				
			||||||
 | 
							void* user_data_or_fixture){
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						CertList *head = newCertListItem( "example.com", NULL, NULL );
 | 
				
			||||||
 | 
						CertList *last = head;
 | 
				
			||||||
 | 
						CertList *curr;
 | 
				
			||||||
 | 
						for ( unsigned int i = 0; i < 10; i++ ){
 | 
				
			||||||
 | 
							char host[15] = {'\0'};
 | 
				
			||||||
 | 
							sprintf(host, "example%d.com", i+1);
 | 
				
			||||||
 | 
							last->next = newCertListItem( strdup(host), NULL, NULL );
 | 
				
			||||||
 | 
							last = last->next;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						munit_assert_int( countCertListItems( head ), ==, 11 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						curr = findCertListItem( head, "example.com" );
 | 
				
			||||||
 | 
						munit_assert_not_null( curr );
 | 
				
			||||||
 | 
						munit_assert_string_equal( curr->host, "example.com" );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						curr = findCertListItem( head, "example1.com" );
 | 
				
			||||||
 | 
						munit_assert_not_null( curr );
 | 
				
			||||||
 | 
						munit_assert_string_equal( curr->host, "example1.com" );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						curr = findCertListItem( head, "example5.com" );
 | 
				
			||||||
 | 
						munit_assert_not_null( curr );
 | 
				
			||||||
 | 
						munit_assert_string_equal( curr->host, "example5.com" );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						curr = findCertListItem( head, "doesnt-exist.com" );
 | 
				
			||||||
 | 
						munit_assert_null( curr );
 | 
				
			||||||
 | 
						return MUNIT_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static char* count_parameters[] = {
 | 
					static char* count_parameters[] = {
 | 
				
			||||||
  "0", "1", "2", "10", "50", NULL
 | 
					  "0", "1", "2", "10", "50", NULL
 | 
				
			||||||
| 
						 | 
					@ -180,6 +211,7 @@ static MunitTest ssl_tests[] = {
 | 
				
			||||||
	{ "/ca/cert/save",    testNewCertificateSave, NULL, NULL,       MUNIT_TEST_OPTION_NONE, NULL },
 | 
						{ "/ca/cert/save",    testNewCertificateSave, NULL, NULL,       MUNIT_TEST_OPTION_NONE, NULL },
 | 
				
			||||||
	{ "/CertList/count",    testCerlistCount, NULL, NULL,       MUNIT_TEST_OPTION_NONE, count_params },
 | 
						{ "/CertList/count",    testCerlistCount, NULL, NULL,       MUNIT_TEST_OPTION_NONE, count_params },
 | 
				
			||||||
	{ "/CertList/last",    testCerlistLast, NULL, NULL,       MUNIT_TEST_OPTION_NONE, count_params },
 | 
						{ "/CertList/last",    testCerlistLast, NULL, NULL,       MUNIT_TEST_OPTION_NONE, count_params },
 | 
				
			||||||
 | 
						{ "/CertList/find",    testFindCertListItem, NULL, NULL,       MUNIT_TEST_OPTION_NONE, NULL },
 | 
				
			||||||
	{ "/hostcert/new",    testNewHostCertificate, NULL, NULL,       MUNIT_TEST_OPTION_NONE, x509_issuer_subject_params },
 | 
						{ "/hostcert/new",    testNewHostCertificate, NULL, NULL,       MUNIT_TEST_OPTION_NONE, x509_issuer_subject_params },
 | 
				
			||||||
/* Mark the end of the array with an entry where the test
 | 
					/* Mark the end of the array with an entry where the test
 | 
				
			||||||
* function is NULL */
 | 
					* function is NULL */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue