From 46f96ed5e3127394a0cd4dcb961404b792f743b4 Mon Sep 17 00:00:00 2001 From: Jakub Slawinski Date: Thu, 10 Jul 2014 10:24:59 +0200 Subject: Initial project structure based on Active Port Forwarder 0.8.4. --- src/first_run.c | 403 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 403 insertions(+) create mode 100644 src/first_run.c (limited to 'src/first_run.c') diff --git a/src/first_run.c b/src/first_run.c new file mode 100644 index 0000000..a023306 --- /dev/null +++ b/src/first_run.c @@ -0,0 +1,403 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static char* home_dir = NULL; +static char* home_dir_store = NULL; +static char* home_dir_key = NULL; +static char* home_dir_cer = NULL; + +typedef struct entry +{ + char *key; + unsigned char *value; +} entryT; + +static +entryT entries[6] = { + {"countryName", (unsigned char*) "PL"}, + {"stateOrProvinceName", (unsigned char*) "War-Maz"}, + {"localityName", (unsigned char*) "Olsztyn"}, + {"organizationName", (unsigned char*) "gray-world.net"}, + {"organizationalUnitName", (unsigned char*) "APF team"}, + {"commonName", (unsigned char*) "Jeremian "}, +}; + +/* + * Function name: callback + * Description: Prints the info about rsa key generation events. + * Arguments: i, j, k - described in the manual page about RSA_generate_key + */ + +static void +callback(int i, int j, void* k) +{ + if (k == NULL) { + printf("%d", i); + fflush(stdout); + } +} + +/* + * Function name: create_apf_dir + * Description: Creates .apf directory in ~/ or apf directory locally. + * Arguments: type - type of the directory to create: + * 0 - .apf in ~/ + * 1 - apf in current dir + * Returns: 0 - success, + * 1 - problems with fetching user info, + * 2 - home directory is not set, + * 3 - calloc failure, + * 4 - directory creation failure. + */ + +int +create_apf_dir(char type) +{ + int length; + struct stat buf; + struct passwd *user = getpwuid(getuid()); + if (type == 0) { + if (user == NULL) { + return 1; /* some problems with fetching user info*/ + } + if (user->pw_dir == NULL) { + return 2; /* home directory is not set? */ + } + if (home_dir) { + free(home_dir); + home_dir = NULL; + } + length = strlen(user->pw_dir); + home_dir = calloc(1, length + 6); + if (home_dir == NULL) { + return 3; /* calloc failed */ + } + strcpy(home_dir, user->pw_dir); + if (home_dir[length] == '/') { + strcpy(&home_dir[length], ".apf"); + } + else { + strcpy(&home_dir[length], "/.apf"); + } + if (stat(home_dir, &buf)) { + if (mkdir(home_dir, 0700)) { + return 4; /* creating directory failed */ + } + } + } + else { + if (home_dir) { + free(home_dir); + home_dir = NULL; + } + home_dir = calloc(1, 4); + if (home_dir == NULL) { + return 3; /* calloc failed */ + } + strcpy(home_dir, "apf"); + if (stat(home_dir, &buf)) { + if (mkdir(home_dir, 0700)) { + return 4; /* creating directory failed */ + } + } + } + return 0; +} + +/* + * Function name: create_publickey_store + * Description: Creates the file to store information about public keys. + * Arguments: storefile - the pointer to filename + * Returns: 0 - success, + * >0 - failure. + */ + +int +create_publickey_store(char** storefile) +{ + int store_length, home_length; + struct stat buf; + FILE* store_file; + assert(storefile != NULL); + assert((*storefile) != NULL); + /* check in local directory first */ + if (stat(*storefile, &buf) == 0) { + return 0; + } + /* check in home_dir */ + store_length = strlen(*storefile); + home_length = strlen(home_dir); + if (home_dir_store) { + free(home_dir_store); + home_dir_store = NULL; + } + home_dir_store = calloc(1, home_length + store_length + 2); + if (home_dir_store == NULL) { + return 1; /* calloc failed */ + } + strcpy(home_dir_store, home_dir); + home_dir_store[home_length] = '/'; + strcpy(&home_dir_store[home_length+1], *storefile); + *storefile = home_dir_store; + store_file = fopen(home_dir_store, "a"); + if (store_file == NULL) { + return 1; + } + fclose(store_file); + if (stat(home_dir_store, &buf) == 0) { + return 0; + } + return 2; +} + +/* + * Function name: generate_rsa_key + * Description: Generates the RSA key. + * Arguments: keyfile - the pointer to filename + * Returns: 0 - success, + * >0 - failure. + */ + +int +generate_rsa_key(char** keyfile) +{ + int key_length, home_length; + RSA* rsa_key; + FILE* rsa_file; + struct stat buf; + assert(keyfile != NULL); + assert((*keyfile) != NULL); + /* check in local directory first */ + if (stat(*keyfile, &buf) == 0) { + return 0; + } + /* check in home_dir */ + key_length = strlen(*keyfile); + home_length = strlen(home_dir); + if (home_dir_key) { + free(home_dir_key); + home_dir_key = NULL; + } + home_dir_key = calloc(1, home_length + key_length + 2); + if (home_dir_key == NULL) { + return 1; /* calloc failed */ + } + strcpy(home_dir_key, home_dir); + home_dir_key[home_length] = '/'; + strcpy(&home_dir_key[home_length+1], *keyfile); + *keyfile = home_dir_key; + if (stat(home_dir_key, &buf) == 0) { + return 0; + } + /* have to generate the key */ + printf("generating rsa key: 2048 bits\n"); + rsa_key = RSA_generate_key(2048, 65537, callback, NULL); + if (RSA_check_key(rsa_key)==1) { + printf(" OK!\n"); + } + else { + printf(" FAILED!\n"); + return 1; + } + + rsa_file = fopen(home_dir_key, "a"); + PEM_write_RSAPrivateKey(rsa_file, rsa_key, NULL, NULL, 0, NULL, NULL); + fclose(rsa_file); + return 0; +} + +/* + * Function name: generate_certificate + * Description: Generates X509 certificate. + * Arguments: cerfile - the pointer to filename + * keyfile - the name of the file with key + * Returns: 0 - success, + * >0 - failure. + */ + +int +generate_certificate(char** cerfile, char* keyfile) +{ + int cer_length, home_length, i; + struct stat buf; + X509* cert; + X509_REQ* req; + X509_NAME* subj; + RSA* rsa_key; + EVP_PKEY* pkey; + const EVP_MD *digest; + FILE* fp; + assert(cerfile != NULL); + assert((*cerfile) != NULL); + assert(keyfile != NULL); + /* check in local directory first */ + if (stat(*cerfile, &buf) == 0) { + return 0; + } + /* check in home_dir */ + cer_length = strlen(*cerfile); + home_length = strlen(home_dir); + if (home_dir_cer) { + free(home_dir_cer); + home_dir_cer = NULL; + } + home_dir_cer = calloc(1, home_length + cer_length + 2); + if (home_dir_cer == NULL) { + return 1; /* calloc failed */ + } + strcpy(home_dir_cer, home_dir); + home_dir_cer[home_length] = '/'; + strcpy(&home_dir_cer[home_length+1], *cerfile); + *cerfile = home_dir_cer; + if (stat(home_dir_cer, &buf) == 0) { + return 0; + } + /* have to generate the certificate */ + printf("generating self signed certificate\n"); + fp = fopen(keyfile, "r"); + if (fp == NULL) { + return 2; /* can't open keyfile */ + } + rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); + fclose(fp); + if (rsa_key == NULL) { + return 3; /* can't read RSAPrivateKey */ + } + pkey = EVP_PKEY_new(); + if (pkey == NULL) { + return 4; /* creating new pkey failed */ + } + if (EVP_PKEY_set1_RSA(pkey, rsa_key) == 0) { + return 5; /* setting rsa key failed */ + } + req = X509_REQ_new(); + if (req == NULL) { + return 6; /* creating new request failed */ + } + X509_REQ_set_pubkey(req, pkey); + subj = X509_NAME_new(); + if (subj == NULL) { + return 7; /* creating new subject name failed */ + } + + for (i = 0; i < 6; i++) + { + int nid; + X509_NAME_ENTRY *ent; + + if ((nid = OBJ_txt2nid(entries[i].key)) == NID_undef) + { + return 8; /* finding NID for a key failed */ + } + ent = X509_NAME_ENTRY_create_by_NID(NULL, nid, MBSTRING_ASC,entries[i].value, -1); + if (ent == NULL) { + return 9; /* creating name entry from NID failed */ + } + if (X509_NAME_add_entry(subj, ent, -1, 0) == 0) { + return 10; /* adding entry to name failed */ + } + } + if (X509_REQ_set_subject_name(req, subj) == 0) { + return 11; /* adding subject to request failed */ + } + + digest = EVP_sha1(); + + if (X509_REQ_sign(req, pkey, digest) == 0) { + return 12; /* signing request failed */ + } + + cert = X509_REQ_to_X509(req, 1000, pkey); + + if (X509_set_version(cert, 2L) == 0) { + return 13; /* setting certificate version failed */ + } + ASN1_INTEGER_set(X509_get_serialNumber(cert), 1); + + if (cert == NULL) { + return 14; /* creating certificate failed */ + } + + if (X509_sign(cert, pkey, digest) == 0) { + return 15; /* signing failed */ + } + + fp = fopen(home_dir_cer, "w"); + if (fp == NULL) { + return 16; /* writing certificate failed */ + } + PEM_write_X509(fp, cert); + fclose(fp); + + EVP_PKEY_free(pkey); + X509_REQ_free(req); + X509_free(cert); + return 0; +} + +/* + * Function name: get_store_filename + * Description: Returns the name of the file for storing information about public keys. + * Returns: The name of the file for storing information about public keys. + */ + +char* +get_store_filename() +{ + return home_dir_store; +} + +/* + * Function name: get_key_filename + * Description: Returns the name of the file with key. + * Returns: The name of the file with key. + */ + +char* +get_key_filename() +{ + return home_dir_key; +} + +/* + * Function name: get_cer_filename + * Description: Returns the name of the file with certificate. + * Returns: The name of the file with certificate. + */ + +char* +get_cer_filename() +{ + return home_dir_cer; +} -- cgit v1.1