]> git.proxmox.com Git - mirror_kronosnet.git/blame - kronosnetd/keygen.c
Merge pull request #227 from ReyRen/openssl-error-mem-free
[mirror_kronosnet.git] / kronosnetd / keygen.c
CommitLineData
ab4c538f 1/*
ec84794b 2 * Copyright (C) 2012-2019 Red Hat, Inc. All rights reserved.
ab4c538f
FDN
3 *
4 * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
5 *
6 * This software licensed under GPL-2.0+, LGPL-2.0+
7 */
8
b1f47355
FDN
9#include "config.h"
10
11#include <stdio.h>
12#include <string.h>
13#include <limits.h>
14#include <unistd.h>
15#include <stdlib.h>
16#include <sys/types.h>
17#include <sys/stat.h>
18#include <fcntl.h>
19
9a5ccc0b
FDN
20#include <libknet.h>
21
b1f47355 22static char *output_file = NULL;
9a5ccc0b 23static ssize_t keylen = KNET_MAX_KEY_LEN;
b1f47355
FDN
24
25static void print_usage(void)
26{
27 printf("\nUsage:\n\n");
28 printf("knet-keygen -o <output_file> [-s <size>]\n\n");
29};
30
31#define OPTION_STRING "ho:s:"
32
33static int read_arguments(int argc, char **argv)
34{
35 int cont = 1;
36 int optchar;
37
38 while (cont) {
39 optchar = getopt(argc, argv, OPTION_STRING);
40
41 switch (optchar) {
42
43 case 'o':
44 output_file = strdup(optarg);
45 if (!output_file) {
46 fprintf(stderr, "Error: Unable to allocate memory\n");
47 return -1;
48 }
49 if (strlen(output_file) > PATH_MAX) {
50 fprintf(stderr, "Seriously? WTF\n");
51 return -1;
52 }
53 break;
54
55 case 's':
56 keylen = atoi(optarg);
9a5ccc0b 57 if ((keylen < KNET_MIN_KEY_LEN) || (keylen > KNET_MAX_KEY_LEN)) {
801bb12d 58 fprintf(stderr, "Error: Key size should be a value between %d and %d (default) included\n",
9a5ccc0b 59 KNET_MIN_KEY_LEN, KNET_MAX_KEY_LEN);
b1f47355
FDN
60 return -1;
61 }
62 break;
63
64 case 'h':
65 print_usage();
66 exit(EXIT_SUCCESS);
67 break;
68
69 case EOF:
70 cont = 0;
71 break;
72
73 default:
74 fprintf(stderr, "Error: unknown option: %c\n", optchar);
75 print_usage();
76 return -1;
77 break;
78
79 }
80 }
81 if (!output_file) {
82 fprintf(stderr, "Error: no output file specified\n");
83 print_usage();
84 return -1;
85 }
86 return 0;
87}
88
89int main (int argc, char *argv[])
90{
91 int ret = 0;
92 int fd = -1;
93 ssize_t res;
94 ssize_t bytes_read = 0;
95 char *keybuf = NULL;
96
97 printf (PACKAGE " key generator.\n");
98
99 if (read_arguments(argc, argv) < 0) {
100 goto exit_error;
101 }
102
103 if (geteuid() != 0) {
104 fprintf(stderr, "Error: Authorization key must be generated as root user.\n");
105 goto exit_error;
106 }
107
108 fd = open ("/dev/random", O_RDONLY);
109 if (fd < 0) {
110 fprintf(stderr, "Error: Unable to open /dev/random\n");
111 goto exit_error;
112 }
113
114 keybuf = malloc(keylen);
115 if (!keybuf) {
116 fprintf(stderr, "Error: Unable to allocate memory for key\n");
117 goto exit_error;
118 }
119
801bb12d 120 printf("Gathering %zd bytes for key from /dev/random.\n", keylen);
b1f47355
FDN
121 printf("This process might take a long time due the amount on entropy required\n");
122 printf("Press keys on your keyboard, perform any kind of disk I/O and/or network to generate entropy faster.\n");
123
124keep_reading:
125 res = read(fd, &keybuf[bytes_read], keylen - bytes_read);
126 if (res == -1) {
127 fprintf(stderr, "Error: Unable to read from /dev/random.\n");
128 goto exit_error;
129 }
130 bytes_read += res;
131 if (bytes_read != keylen) {
801bb12d 132 printf("bytes read = %zd, missing = %zd.\n", bytes_read, keylen - bytes_read);
b1f47355
FDN
133 goto keep_reading;
134 }
135 close (fd);
136 fd = -1;
137
138 fd = open (output_file, O_CREAT|O_WRONLY, 600);
139 if (fd == -1) {
140 fprintf(stderr, "Error: Could not create %s\n", output_file);
141 goto exit_error;
142 }
143
144 /*
145 * Make sure file is owned by root and mode 0400
146 */
147 if (fchown(fd, 0, 0)) {
148 fprintf(stderr, "Error: Could not set uid 0 (root) and gid 0 (root) on keyfile %s\n", output_file);
149 goto exit_error;
150 }
151 if (fchmod(fd, 0400)) {
152 fprintf(stderr, "Error: Could not set read-only permissions on keyfile %s\n", output_file);
153 goto exit_error;
154 }
155
156 printf("Writing private key to %s\n", output_file);
157
158 if (write(fd, keybuf, keylen) != keylen) {
159 fprintf(stderr, "Error: Could not write key to file %s\n", output_file);
160 goto exit_error;
161 }
162
163 printf("Done.\n");
164 printf("Please copy this file in " DEFAULT_CONFIG_DIR "/cryptokeys.d/<knet_interface_name>\n");
165 printf("on all nodes participating in the same kronosnet instance\n");
166
167exit_clean:
168 if (output_file)
169 free(output_file);
170 if (keybuf)
171 free(keybuf);
172 if (fd > -1)
173 close(fd);
174
175 return ret;
176
177exit_error:
178 ret = -1;
179 goto exit_clean;
180}