Replace obsolete getpass()
[vpnc.git] / crypto.c
blobf652af6d5a2120e4650cf4ddfb1faa5c9b987def
1 /* IPSec VPN client compatible with Cisco equipment.
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2 of the License, or
6 (at your option) any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 #include <stdio.h>
19 #include <stdarg.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <sys/stat.h>
23 #include <fcntl.h>
24 #include <limits.h>
25 #include <unistd.h>
26 #include <errno.h>
28 #include "sysdep.h"
29 #include "crypto.h"
32 #define MSG_SIZE 200
33 void crypto_error_set(crypto_error **error,
34 int code,
35 int in_errno,
36 const char *fmt, ...)
38 va_list args;
40 if (!error)
41 return;
42 if (*error) {
43 fprintf(stderr, "%s: called with non-NULL *error\n", __func__);
44 return;
47 *error = calloc(1, sizeof(crypto_error));
48 if (!*error)
49 return;
51 (*error)->code = code;
52 (*error)->err = in_errno;
54 (*error)->msg = malloc(MSG_SIZE);
55 if (!(*error)->msg) {
56 fprintf(stderr, "%s: not enough memory for error message\n", __func__);
57 crypto_error_clear(error);
58 return;
61 va_start(args, fmt);
62 if (vsnprintf((*error)->msg, MSG_SIZE, fmt, args) == -1)
63 (*error)->msg[0] = '\0';
64 va_end(args);
67 void crypto_error_free(crypto_error *error)
69 if (error) {
70 if (error->msg)
71 free(error->msg);
72 memset(error, 0, sizeof(crypto_error));
73 free(error);
77 void crypto_error_clear(crypto_error **error)
79 if (error && *error) {
80 crypto_error_free(*error);
81 *error = NULL;
85 void crypto_call_error(crypto_error *err)
87 if (err)
88 error(err->code, err->err, "%s\n", err->msg);
89 else
90 error(1, 0, "unknown error");
93 unsigned char *
94 crypto_read_file(const char *path, size_t *out_len, crypto_error **error)
96 struct stat st;
97 int fd;
98 ssize_t bytes_read;
99 size_t file_size;
100 unsigned char *data = NULL;
102 *out_len = 0;
104 fd = open(path, O_RDONLY);
105 if (fd < 0) {
106 crypto_error_set(error, 1, errno, "failed to open file '%s'", path);
107 return NULL;
110 if (fstat(fd, &st) < 0) {
111 crypto_error_set(error, 1, errno, "failed to stat file '%s'", path);
112 goto out;
115 if (st.st_size <= 0 || st.st_size > INT_MAX) {
116 crypto_error_set(error, 1, errno, "invalid file '%s' length %ld", path, st.st_size);
117 goto out;
120 file_size = st.st_size;
121 data = malloc(file_size);
122 if (!data) {
123 crypto_error_set(error, 1, ENOMEM, "not enough memory to read file '%s'", path);
124 goto out;
127 do {
128 bytes_read = read(fd, &(data[*out_len]), (st.st_size - *out_len));
129 if (bytes_read < 0) {
130 free(data);
131 data = NULL;
132 *out_len = 0;
133 crypto_error_set(error, 1, errno, "failed to read file '%s'", path);
134 goto out;
136 *out_len += bytes_read;
137 } while ((bytes_read > 0) && (*out_len <= file_size));
139 out:
140 close(fd);
141 return data;