c6dde5a62eec7b8f72805582ddedc83ebb49faab
[strongswan.git] / src / pluto / defs.c
1 /* misc. universal things
2 * Copyright (C) 1998-2001 D. Hugh Redelmeier.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * RCSID $Id$
15 */
16
17 #include <stdlib.h>
18 #include <string.h>
19 #include <stdio.h>
20 #include <dirent.h>
21 #include <time.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24
25 #include <freeswan.h>
26
27 #include "constants.h"
28 #include "defs.h"
29 #include "log.h"
30 #include "whack.h" /* for RC_LOG_SERIOUS */
31
32 /**
33 * Empty chunk.
34 */
35 const chunk_t chunk_empty = { NULL, 0 };
36
37 /**
38 * Create a clone of a chunk pointing to "ptr"
39 */
40 chunk_t chunk_create_clone(u_char *ptr, chunk_t chunk)
41 {
42 chunk_t clone = chunk_empty;
43
44 if (chunk.ptr && chunk.len > 0)
45 {
46 clone.ptr = ptr;
47 clone.len = chunk.len;
48 memcpy(clone.ptr, chunk.ptr, chunk.len);
49 }
50 return clone;
51 }
52
53 bool
54 all_zero(const unsigned char *m, size_t len)
55 {
56 size_t i;
57
58 for (i = 0; i != len; i++)
59 if (m[i] != '\0')
60 return FALSE;
61 return TRUE;
62 }
63
64 void *clone_bytes(const void *orig, size_t size)
65 {
66 void *p = malloc(size);
67
68 memcpy(p, orig, size);
69 return p;
70 }
71
72 /* Note that there may be as many as six IDs that are temporary at
73 * one time before unsharing the two ends of a connection. So we need
74 * at least six temporary buffers for DER_ASN1_DN IDs.
75 * We rotate them. Be careful!
76 */
77 #define MAX_BUF 10
78
79 char*
80 temporary_cyclic_buffer(void)
81 {
82 static char buf[MAX_BUF][BUF_LEN]; /* MAX_BUF internal buffers */
83 static int counter = 0; /* cyclic counter */
84
85 if (++counter == MAX_BUF) counter = 0; /* next internal buffer */
86 return buf[counter]; /* assign temporary buffer */
87 }
88
89 /* concatenates two sub paths into a string with a maximum size of BUF_LEN
90 * use for temporary storage only
91 */
92 const char*
93 concatenate_paths(const char *a, const char *b)
94 {
95 char *c;
96
97 if (*b == '/' || *b == '.')
98 return b;
99
100 c = temporary_cyclic_buffer();
101 snprintf(c, BUF_LEN, "%s/%s", a, b);
102 return c;
103 }
104
105 /* compare two chunks, returns zero if a equals b
106 * negative/positive if a is earlier/later in the alphabet than b
107 */
108 int chunk_compare(chunk_t a, chunk_t b)
109 {
110 int compare_len = a.len - b.len;
111 int len = (compare_len < 0)? a.len : b.len;
112
113 if (compare_len != 0 || len == 0)
114 {
115 return compare_len;
116 }
117 return memcmp(a.ptr, b.ptr, len);
118 }
119
120 /* moves a chunk to a memory position, chunk is freed afterwards
121 * position pointer is advanced after the insertion point
122 */
123 void
124 mv_chunk(u_char **pos, chunk_t content)
125 {
126 if (content.len > 0)
127 {
128 chunkcpy(*pos, content);
129 free(content.ptr);
130 }
131 }
132
133 /*
134 * write the binary contents of a chunk_t to a file
135 */
136 bool
137 write_chunk(const char *filename, const char *label, chunk_t ch
138 , mode_t mask, bool force)
139 {
140 mode_t oldmask;
141 FILE *fd;
142 size_t written;
143
144 if (!force)
145 {
146 fd = fopen(filename, "r");
147 if (fd)
148 {
149 fclose(fd);
150 plog(" %s file '%s' already exists", label, filename);
151 return FALSE;
152 }
153 }
154
155 /* set umask */
156 oldmask = umask(mask);
157
158 fd = fopen(filename, "w");
159
160 if (fd)
161 {
162 written = fwrite(ch.ptr, sizeof(u_char), ch.len, fd);
163 fclose(fd);
164 if (written != ch.len)
165 {
166 plog(" writing to %s file '%s' failed", label, filename);
167 umask(oldmask);
168 return FALSE;
169 }
170 plog(" written %s file '%s' (%d bytes)", label, filename, (int)ch.len);
171 umask(oldmask);
172 return TRUE;
173 }
174 else
175 {
176 plog(" could not open %s file '%s' for writing", label, filename);
177 umask(oldmask);
178 return FALSE;
179 }
180 }
181
182 /* Names of the months */
183
184 static const char* months[] = {
185 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
186 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
187 };
188
189
190 /*
191 * Display a date either in local or UTC time
192 */
193 char*
194 timetoa(const time_t *time, bool utc)
195 {
196 static char buf[TIMETOA_BUF];
197
198 if (*time == UNDEFINED_TIME)
199 sprintf(buf, "--- -- --:--:--%s----", (utc)?" UTC ":" ");
200 else
201 {
202 struct tm *t = (utc)? gmtime(time) : localtime(time);
203
204 sprintf(buf, "%s %02d %02d:%02d:%02d%s%04d",
205 months[t->tm_mon], t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec,
206 (utc)?" UTC ":" ", t->tm_year + 1900
207 );
208 }
209 return buf;
210 }
211
212 /* checks if the expiration date has been reached and
213 * warns during the warning_interval of the imminent
214 * expiry. strict=TRUE declares a fatal error,
215 * strict=FALSE issues a warning upon expiry.
216 */
217 const char*
218 check_expiry(time_t expiration_date, int warning_interval, bool strict)
219 {
220 time_t now;
221 int time_left;
222
223 if (expiration_date == UNDEFINED_TIME)
224 return "ok (expires never)";
225
226 /* determine the current time */
227 time(&now);
228
229 time_left = (expiration_date - now);
230 if (time_left < 0)
231 return strict? "fatal (expired)" : "warning (expired)";
232
233 if (time_left > 86400*warning_interval)
234 return "ok";
235 {
236 static char buf[35]; /* temporary storage */
237 const char* unit = "second";
238
239 if (time_left > 172800)
240 {
241 time_left /= 86400;
242 unit = "day";
243 }
244 else if (time_left > 7200)
245 {
246 time_left /= 3600;
247 unit = "hour";
248 }
249 else if (time_left > 120)
250 {
251 time_left /= 60;
252 unit = "minute";
253 }
254 snprintf(buf, 35, "warning (expires in %d %s%s)", time_left,
255 unit, (time_left == 1)?"":"s");
256 return buf;
257 }
258 }
259
260
261 /*
262 * Filter eliminating the directory entries '.' and '..'
263 */
264 int
265 file_select(const struct dirent *entry)
266 {
267 return strcmp(entry->d_name, "." ) &&
268 strcmp(entry->d_name, "..");
269 }
270
271