summaryrefslogtreecommitdiff
path: root/src/first_run.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/first_run.c')
-rw-r--r--src/first_run.c286
1 files changed, 238 insertions, 48 deletions
diff --git a/src/first_run.c b/src/first_run.c
index 842a3e0..4c866c0 100644
--- a/src/first_run.c
+++ b/src/first_run.c
@@ -28,52 +28,148 @@
#include <sys/stat.h>
#include <sys/wait.h>
#include <pwd.h>
+#include <openssl/rsa.h>
+#include <openssl/pem.h>
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 <jeremian [at] poczta [dot] fm>"},
+};
+
+static void
+callback(int i, int j, void* k)
+{
+ if (k == NULL) {
+ printf("%d", i);
+ fflush(stdout);
+ }
+}
+
+/*
+ * 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()
+create_apf_dir(char type)
{
int length;
struct stat buf;
struct passwd *user = getpwuid(getuid());
- if (user == NULL) {
- return 1; /* some problems witch fetching user info*/
+ 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 */
+ }
+ }
}
- if (user->pw_dir == NULL) {
- return 2; /* home directory is not set? */
+ 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 */
+ }
+ }
}
- if (home_dir) {
- free(home_dir);
- home_dir = NULL;
+ return 0;
+}
+
+int
+create_publickey_store(char** storefile)
+{
+ int store_length, home_length;
+ struct stat buf;
+ FILE* store_file;
+ /* check in local directory first */
+ if (stat(*storefile, &buf) == 0) {
+ return 0;
}
- length = strlen(user->pw_dir);
- home_dir = calloc(1, length + 6);
- if (home_dir == NULL) {
- return 3; /* calloc failed */
+ /* 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;
}
- strcpy(home_dir, user->pw_dir);
- if (home_dir[length] == '/') {
- strcpy(&home_dir[length], ".apf");
+ home_dir_store = calloc(1, home_length + store_length + 2);
+ if (home_dir_store == NULL) {
+ return 1; /* calloc failed */
}
- else {
- strcpy(&home_dir[length], "/.apf");
+ 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;
}
- if (stat(home_dir, &buf)) {
- if (mkdir(home_dir, 0700)) {
- return 4; /* creating directory failed */
- }
+ fclose(store_file);
+ if (stat(home_dir_store, &buf) == 0) {
+ return 0;
}
- return 0;
+ return 2;
}
int
generate_rsa_key(char** keyfile)
{
- int key_length, home_length, status;
- char openssl_cmd[101];
+ int key_length, home_length;
+ RSA* rsa_key;
+ FILE* rsa_file;
struct stat buf;
/* check in local directory first */
if (stat(*keyfile, &buf) == 0) {
@@ -98,22 +194,34 @@ generate_rsa_key(char** keyfile)
return 0;
}
/* have to generate the key */
- if (snprintf(openssl_cmd, 101, "openssl genrsa -out %s 2048", home_dir_key) > 100) {
- return 2; /* string is too long */
+ 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");
}
- status = system(openssl_cmd);
- if (status == -1) {
- return -1;
+ else {
+ printf(" FAILED!\n");
+ return 1;
}
- return WEXITSTATUS(status);
+
+ rsa_file = fopen(home_dir_key, "a");
+ PEM_write_RSAPrivateKey(rsa_file, rsa_key, NULL, NULL, 0, NULL, NULL);
+ fclose(rsa_file);
+ return 0;
}
int
generate_certificate(char** cerfile, char* keyfile)
{
- int cer_length, home_length, status, tmp_fd1, tmp_fd2;
- char openssl_cmd[301];
+ 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;
/* check in local directory first */
if (stat(*cerfile, &buf) == 0) {
return 0;
@@ -137,20 +245,102 @@ generate_certificate(char** cerfile, char* keyfile)
return 0;
}
/* have to generate the certificate */
- if (snprintf(openssl_cmd, 201, "echo -e \"pl\nWar-Maz\nOlsztyn\nSHEG\nUtils productions\njeremian\njeremian@poczta.fm\" | openssl req -new -x509 -key %s -out %s -days 1095", keyfile, home_dir_cer) > 300) {
- return 2; /* string is too long */
- }
- tmp_fd1 = dup(STDOUT_FILENO);
- tmp_fd2 = dup(STDERR_FILENO);
- close(STDOUT_FILENO);
- close(STDERR_FILENO);
- status = system(openssl_cmd);
- dup2(tmp_fd1, STDOUT_FILENO);
- dup2(tmp_fd2, STDERR_FILENO);
- close(tmp_fd1);
- close(tmp_fd2);
- if (status == -1) {
- return -1;
- }
- return WEXITSTATUS(status);
+ 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;
+}
+
+char*
+get_store_filename()
+{
+ return home_dir_store;
+}
+
+char*
+get_key_filename()
+{
+ return home_dir_key;
+}
+
+char*
+get_cer_filename()
+{
+ return home_dir_cer;
}