1 /* Copyright (C) 2009 Trend Micro Inc.
4 * This program is a free software; you can redistribute it
5 * and/or modify it under the terms of the GNU General Public
6 * License (version 2) as published by the FSF - Free Software
10 #include "headers/shared.h"
11 #include "headers/sec.h"
12 #include "os_crypto/md5/md5_op.h"
13 #include "os_crypto/blowfish/bf_op.h"
16 static void __memclear(char *id, char *name, char *ip, char *key, size_t size) __attribute((nonnull));
17 static void __chash(keystore *keys, const char *id, const char *name, char *ip, const char *key) __attribute((nonnull));
19 static int pass_empty_keyfile = 0;
21 /* Clear keys entries */
22 static void __memclear(char *id, char *name, char *ip, char *key, size_t size)
24 memset(id, '\0', size);
25 memset(name, '\0', size);
26 memset(key, '\0', size);
27 memset(ip, '\0', size);
30 /* Create the final key */
31 static void __chash(keystore *keys, const char *id, const char *name, char *ip, const char *key)
37 char _finalstr[KEYSIZE];
39 /* Allocate for the whole structure */
40 keys->keyentries = (keyentry **)realloc(keys->keyentries,
41 (keys->keysize + 2) * sizeof(keyentry *));
42 if (!keys->keyentries) {
43 ErrorExit(MEM_ERROR, __local_name, errno, strerror(errno));
45 os_calloc(1, sizeof(keyentry), keys->keyentries[keys->keysize]);
47 /* Set configured values for id */
48 os_strdup(id, keys->keyentries[keys->keysize]->id);
49 OSHash_Add(keys->keyhash_id,
50 keys->keyentries[keys->keysize]->id,
51 keys->keyentries[keys->keysize]);
54 os_calloc(1, sizeof(os_ip), keys->keyentries[keys->keysize]->ip);
55 if (OS_IsValidIP(ip, keys->keyentries[keys->keysize]->ip) == 0) {
56 ErrorExit(INVALID_IP, __local_name, ip);
59 /* We need to remove the "/" from the CIDR */
60 if ((tmp_str = strchr(keys->keyentries[keys->keysize]->ip->ip, '/')) != NULL) {
63 OSHash_Add(keys->keyhash_ip,
64 keys->keyentries[keys->keysize]->ip->ip,
65 keys->keyentries[keys->keysize]);
68 os_strdup(name, keys->keyentries[keys->keysize]->name);
70 /* Initialize the variables */
71 keys->keyentries[keys->keysize]->rcvd = 0;
72 keys->keyentries[keys->keysize]->local = 0;
73 keys->keyentries[keys->keysize]->keyid = keys->keysize;
74 keys->keyentries[keys->keysize]->global = 0;
75 keys->keyentries[keys->keysize]->fp = NULL;
77 /** Generate final symmetric key **/
79 /* MD5 from name, id and key */
80 OS_MD5_Str(name, filesum1);
81 OS_MD5_Str(id, filesum2);
83 /* Generate new filesum1 */
84 snprintf(_finalstr, sizeof(_finalstr) - 1, "%s%s", filesum1, filesum2);
86 /* Use just half of the first MD5 (name/id) */
87 OS_MD5_Str(_finalstr, filesum1);
91 /* Second md is just the key */
92 OS_MD5_Str(key, filesum2);
94 /* Generate final key */
95 snprintf(_finalstr, 49, "%s%s", filesum2, filesum1);
97 /* Final key is 48 * 4 = 192bits */
98 os_strdup(_finalstr, keys->keyentries[keys->keysize]->key);
100 /* Clean final string from memory */
101 memset_secure(_finalstr, '\0', sizeof(_finalstr));
109 /* Check if the authentication key file is present */
114 if (File_DateofChange(KEYSFILE_PATH) < 0) {
115 merror(NO_AUTHFILE, __local_name, KEYSFILE_PATH);
116 merror(NO_CLIENT_KEYS, __local_name);
120 fp = fopen(KEYSFILE_PATH, "r");
122 /* We can leave from here */
123 merror(FOPEN_ERROR, __local_name, KEYSFILE_PATH, errno, strerror(errno));
124 merror(NO_AUTHFILE, __local_name, KEYSFILE_PATH);
125 merror(NO_CLIENT_KEYS, __local_name);
131 /* Authentication keys are present */
135 /* Read the authentication keys */
136 void OS_ReadKeys(keystore *keys)
140 char buffer[OS_BUFFER_SIZE + 1];
142 char name[KEYSIZE + 1];
143 char ip[KEYSIZE + 1];
144 char id[KEYSIZE + 1];
145 char key[KEYSIZE + 1];
147 /* Check if the keys file is present and we can read it */
148 if ((keys->file_change = File_DateofChange(KEYS_FILE)) < 0) {
149 merror(NO_AUTHFILE, __local_name, KEYS_FILE);
150 ErrorExit(NO_CLIENT_KEYS, __local_name);
153 fp = fopen(KEYS_FILE, "r");
155 /* We can leave from here */
156 merror(FOPEN_ERROR, __local_name, KEYS_FILE, errno, strerror(errno));
157 ErrorExit(NO_CLIENT_KEYS, __local_name);
161 /* Initialize hashes */
162 keys->keyhash_id = OSHash_Create();
163 keys->keyhash_ip = OSHash_Create();
164 if (!keys->keyhash_id || !keys->keyhash_ip) {
165 ErrorExit(MEM_ERROR, __local_name, errno, strerror(errno));
168 /* Initialize structure */
169 os_calloc(1, sizeof(keyentry*), keys->keyentries);
172 /* Zero the buffers */
173 __memclear(id, name, ip, key, KEYSIZE + 1);
174 memset(buffer, '\0', OS_BUFFER_SIZE + 1);
176 /* Read each line. Lines are divided as "id name ip key" */
177 while (fgets(buffer, OS_BUFFER_SIZE, fp) != NULL) {
181 if ((buffer[0] == '#') || (buffer[0] == ' ')) {
187 tmp_str = strchr(buffer, ' ');
189 merror(INVALID_KEY, __local_name, buffer);
195 strncpy(id, valid_str, KEYSIZE - 1);
198 if (*tmp_str == '#') {
204 tmp_str = strchr(tmp_str, ' ');
206 merror(INVALID_KEY, __local_name, buffer);
212 strncpy(name, valid_str, KEYSIZE - 1);
216 tmp_str = strchr(tmp_str, ' ');
218 merror(INVALID_KEY, __local_name, buffer);
224 strncpy(ip, valid_str, KEYSIZE - 1);
228 tmp_str = strchr(tmp_str, '\n');
233 strncpy(key, valid_str, KEYSIZE - 1);
235 /* Generate the key hash */
236 __chash(keys, id, name, ip, key);
238 /* Clear the memory */
239 __memclear(id, name, ip, key, KEYSIZE + 1);
241 /* Check for maximum agent size */
242 if (keys->keysize >= (MAX_AGENTS - 2)) {
243 merror(AG_MAX_ERROR, __local_name, MAX_AGENTS - 2);
244 ErrorExit(CONFIG_ERROR, __local_name, KEYS_FILE);
253 /* Clear one last time before leaving */
254 __memclear(id, name, ip, key, KEYSIZE + 1);
256 /* Check if there are any agents available */
257 if (keys->keysize == 0) {
258 merror(NO_CLIENT_KEYS, __local_name);
259 if (!pass_empty_keyfile) {
264 /* Add additional entry for sender == keysize */
265 os_calloc(1, sizeof(keyentry), keys->keyentries[keys->keysize]);
270 /* Free the auth keys */
271 void OS_FreeKeys(keystore *keys)
274 unsigned int _keysize = 0;
278 _keysize = keys->keysize;
279 hashid = keys->keyhash_id;
280 haship = keys->keyhash_ip;
282 /* Zero the entries */
284 keys->keyhash_id = NULL;
285 keys->keyhash_ip = NULL;
287 /* Sleep to give time to other threads to stop using them */
290 /* Free the hashes */
294 for (i = 0; i <= _keysize; i++) {
295 if (keys->keyentries[i]) {
296 if (keys->keyentries[i]->ip) {
297 free(keys->keyentries[i]->ip->ip);
298 free(keys->keyentries[i]->ip);
301 if (keys->keyentries[i]->id) {
302 free(keys->keyentries[i]->id);
305 if (keys->keyentries[i]->key) {
306 free(keys->keyentries[i]->key);
309 if (keys->keyentries[i]->name) {
310 free(keys->keyentries[i]->name);
314 if (keys->keyentries[i]->fp) {
315 fclose(keys->keyentries[i]->fp);
318 free(keys->keyentries[i]);
319 keys->keyentries[i] = NULL;
324 free(keys->keyentries);
325 keys->keyentries = NULL;
329 /* Check if key changed */
330 int OS_CheckUpdateKeys(const keystore *keys)
332 if (keys->file_change != File_DateofChange(KEYS_FILE)) {
338 /* Update the keys if changed */
339 int OS_UpdateKeys(keystore *keys)
341 if (keys->file_change != File_DateofChange(KEYS_FILE)) {
342 merror(ENCFILE_CHANGED, __local_name);
343 debug1("%s: DEBUG: Freekeys", __local_name);
346 debug1("%s: DEBUG: OS_ReadKeys", __local_name);
349 verbose(ENC_READ, __local_name);
352 debug1("%s: DEBUG: OS_StartCounter", __local_name);
354 OS_StartCounter(keys);
355 debug1("%s: DEBUG: OS_UpdateKeys completed", __local_name);
362 /* Check if an IP address is allowed to connect */
363 int OS_IsAllowedIP(keystore *keys, const char *srcip)
371 entry = (keyentry *) OSHash_Get(keys->keyhash_ip, srcip);
373 return ((int)entry->keyid);
379 /* Check if the agent name is valid */
380 int OS_IsAllowedName(const keystore *keys, const char *name)
384 for (i = 0; i < keys->keysize; i++) {
385 if (strcmp(keys->keyentries[i]->name, name) == 0) {
393 int OS_IsAllowedID(keystore *keys, const char *id)
401 entry = (keyentry *) OSHash_Get(keys->keyhash_id, id);
403 return ((int)entry->keyid);
409 /* Used for dynamic IP addresses */
410 int OS_IsAllowedDynamicID(keystore *keys, const char *id, const char *srcip)
418 entry = (keyentry *) OSHash_Get(keys->keyhash_id, id);
420 if (OS_IPFound(srcip, entry->ip)) {
421 return ((int)entry->keyid);
427 /* Configure to pass if keys file is empty */
428 void OS_PassEmptyKeyfile() {
429 pass_empty_keyfile = 1;