new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / os_crypto / shared / keys.c
old mode 100755 (executable)
new mode 100644 (file)
index 587f083..5d37b23
@@ -1,6 +1,3 @@
-/* @(#) $Id: ./src/os_crypto/shared/keys.c, 2011/09/08 dcid Exp $
- */
-
 /* Copyright (C) 2009 Trend Micro Inc.
  * All rights reserved.
  *
  * and/or modify it under the terms of the GNU General Public
  * License (version 2) as published by the FSF - Free Software
  * Foundation.
- *
- * License details at the LICENSE file included with OSSEC or
- * online at: http://www.ossec.net/en/licensing.html
  */
 
-
-
 #include "headers/shared.h"
 #include "headers/sec.h"
-
-#include "os_zlib/os_zlib.h"
 #include "os_crypto/md5/md5_op.h"
 #include "os_crypto/blowfish/bf_op.h"
 
+/* Prototypes */
+static void __memclear(char *id, char *name, char *ip, char *key, size_t size) __attribute((nonnull));
+static void __chash(keystore *keys, const char *id, const char *name, char *ip, const char *key) __attribute((nonnull));
 
+static int pass_empty_keyfile = 0;
 
-/* __memclear: Clears keys entries.
- */
-void __memclear(char *id, char *name, char *ip, char *key, int size)
+/* Clear keys entries */
+static void __memclear(char *id, char *name, char *ip, char *key, size_t size)
 {
-       memset(id,'\0', size);
-       memset(name,'\0', size);
-       memset(key,'\0', size);
-       memset(ip,'\0', size);
+    memset(id, '\0', size);
+    memset(name, '\0', size);
+    memset(key, '\0', size);
+    memset(ip, '\0', size);
 }
 
-
-/* __chash: Creates the final key.
- */
-void __chash(keystore *keys, char *id, char *name, char *ip, char *key)
+/* Create the final key */
+static void __chash(keystore *keys, const char *id, const char *name, char *ip, const char *key)
 {
-       os_md5 filesum1;
-       os_md5 filesum2;
+    os_md5 filesum1;
+    os_md5 filesum2;
 
     char *tmp_str;
-       char _finalstr[KEYSIZE];
-
+    char _finalstr[KEYSIZE];
 
-    /* Allocating for the whole structure */
-    keys->keyentries =(keyentry **)realloc(keys->keyentries,
-                                         (keys->keysize+2)*sizeof(keyentry *));
-    if(!keys->keyentries)
-    {
-        ErrorExit(MEM_ERROR, __local_name);
+    /* Allocate for the whole structure */
+    keys->keyentries = (keyentry **)realloc(keys->keyentries,
+                                            (keys->keysize + 2) * sizeof(keyentry *));
+    if (!keys->keyentries) {
+        ErrorExit(MEM_ERROR, __local_name, errno, strerror(errno));
     }
     os_calloc(1, sizeof(keyentry), keys->keyentries[keys->keysize]);
 
-
-    /* Setting configured values for id */
+    /* Set configured values for id */
     os_strdup(id, keys->keyentries[keys->keysize]->id);
     OSHash_Add(keys->keyhash_id,
                keys->keyentries[keys->keysize]->id,
                keys->keyentries[keys->keysize]);
 
-
-    /* agent ip */
+    /* Agent IP */
     os_calloc(1, sizeof(os_ip), keys->keyentries[keys->keysize]->ip);
-    if(OS_IsValidIP(ip, keys->keyentries[keys->keysize]->ip) == 0)
-    {
+    if (OS_IsValidIP(ip, keys->keyentries[keys->keysize]->ip) == 0) {
         ErrorExit(INVALID_IP, __local_name, ip);
     }
 
-    /* We need to remove the "/" from the cidr */
-       if((tmp_str = strchr(keys->keyentries[keys->keysize]->ip->ip, '/')) != NULL)
-    {
+    /* We need to remove the "/" from the CIDR */
+    if ((tmp_str = strchr(keys->keyentries[keys->keysize]->ip->ip, '/')) != NULL) {
         *tmp_str = '\0';
     }
     OSHash_Add(keys->keyhash_ip,
                keys->keyentries[keys->keysize]->ip->ip,
                keys->keyentries[keys->keysize]);
 
-
-    /* agent name */
+    /* Agent name */
     os_strdup(name, keys->keyentries[keys->keysize]->name);
 
-    /* Initializing the variables */
+    /* Initialize the variables */
     keys->keyentries[keys->keysize]->rcvd = 0;
     keys->keyentries[keys->keysize]->local = 0;
     keys->keyentries[keys->keysize]->keyid = keys->keysize;
     keys->keyentries[keys->keysize]->global = 0;
     keys->keyentries[keys->keysize]->fp = NULL;
 
-       
-
-       /** Generating final symmetric key **/
-
-       /* MD5 from name, id and key */
-       OS_MD5_Str(name, filesum1);     
-       OS_MD5_Str(id,  filesum2);
+    /** Generate final symmetric key **/
 
+    /* MD5 from name, id and key */
+    OS_MD5_Str(name, filesum1);
+    OS_MD5_Str(id,  filesum2);
 
-       /* Generating new filesum1 */
-       snprintf(_finalstr, sizeof(_finalstr)-1, "%s%s", filesum1, filesum2);
+    /* Generate new filesum1 */
+    snprintf(_finalstr, sizeof(_finalstr) - 1, "%s%s", filesum1, filesum2);
 
-       
-    /* Using just half of the first md5 (name/id) */
+    /* Use just half of the first MD5 (name/id) */
     OS_MD5_Str(_finalstr, filesum1);
-    filesum1[15] = '\0';       
+    filesum1[15] = '\0';
     filesum1[16] = '\0';
 
-
     /* Second md is just the key */
-    OS_MD5_Str(key, filesum2); 
-       
-
-       /* Generating final key */
-       memset(_finalstr,'\0', sizeof(_finalstr));
-       snprintf(_finalstr, 49, "%s%s", filesum2, filesum1);
+    OS_MD5_Str(key, filesum2);
 
+    /* Generate final key */
+    snprintf(_finalstr, 49, "%s%s", filesum2, filesum1);
 
     /* Final key is 48 * 4 = 192bits */
     os_strdup(_finalstr, keys->keyentries[keys->keysize]->key);
 
+    /* Clean final string from memory */
+    memset_secure(_finalstr, '\0', sizeof(_finalstr));
 
-       /* Cleaning final string from memory */
-       memset(_finalstr,'\0', sizeof(_finalstr));
-
-
-       /* ready for next */
-       keys->keysize++;        
-
+    /* Ready for next */
+    keys->keysize++;
 
-       return;
+    return;
 }
 
-
-/* int OS_CheckKeys():
- * Checks if the authentication key file is present
- */
+/* Check if the authentication key file is present */
 int OS_CheckKeys()
 {
     FILE *fp;
 
-    if(File_DateofChange(KEYSFILE_PATH) < 0)
-    {
+    if (File_DateofChange(KEYSFILE_PATH) < 0) {
         merror(NO_AUTHFILE, __local_name, KEYSFILE_PATH);
-        merror(NO_REM_CONN, __local_name);
-        return(0);
+        merror(NO_CLIENT_KEYS, __local_name);
+        return (0);
     }
 
     fp = fopen(KEYSFILE_PATH, "r");
-    if(!fp)
-    {
+    if (!fp) {
         /* We can leave from here */
-        merror(FOPEN_ERROR, __local_name, KEYSFILE_PATH);
+        merror(FOPEN_ERROR, __local_name, KEYSFILE_PATH, errno, strerror(errno));
         merror(NO_AUTHFILE, __local_name, KEYSFILE_PATH);
-        merror(NO_REM_CONN, __local_name);
-        return(0);
+        merror(NO_CLIENT_KEYS, __local_name);
+        return (0);
     }
 
     fclose(fp);
 
-
     /* Authentication keys are present */
-    return(1);
+    return (1);
 }
 
-
-/* void OS_ReadKeys(keystore *keys)
- * Read the authentication keys.
- */
+/* Read the authentication keys */
 void OS_ReadKeys(keystore *keys)
 {
     FILE *fp;
 
-    char buffer[OS_BUFFER_SIZE +1];
-
-    char name[KEYSIZE +1];
-    char ip[KEYSIZE +1];
-    char id[KEYSIZE +1];
-    char key[KEYSIZE +1];
+    char buffer[OS_BUFFER_SIZE + 1];
 
+    char name[KEYSIZE + 1];
+    char ip[KEYSIZE + 1];
+    char id[KEYSIZE + 1];
+    char key[KEYSIZE + 1];
 
-    /* Checking if the keys file is present and we can read it. */
-    if((keys->file_change = File_DateofChange(KEYS_FILE)) < 0)
-    {
+    /* Check if the keys file is present and we can read it */
+    if ((keys->file_change = File_DateofChange(KEYS_FILE)) < 0) {
         merror(NO_AUTHFILE, __local_name, KEYS_FILE);
-        ErrorExit(NO_REM_CONN, __local_name);
+        ErrorExit(NO_CLIENT_KEYS, __local_name);
+
     }
-    fp = fopen(KEYS_FILE,"r");
-    if(!fp)
-    {
+    fp = fopen(KEYS_FILE, "r");
+    if (!fp) {
         /* We can leave from here */
-        merror(FOPEN_ERROR, __local_name, KEYS_FILE);
-        ErrorExit(NO_REM_CONN, __local_name);
-    }
+        merror(FOPEN_ERROR, __local_name, KEYS_FILE, errno, strerror(errno));
+        ErrorExit(NO_CLIENT_KEYS, __local_name);
 
+    }
 
-    /* Initilizing hashes */
+    /* Initialize hashes */
     keys->keyhash_id = OSHash_Create();
     keys->keyhash_ip = OSHash_Create();
-    if(!keys->keyhash_id || !keys->keyhash_ip)
-    {
-        ErrorExit(MEM_ERROR, __local_name);
+    if (!keys->keyhash_id || !keys->keyhash_ip) {
+        ErrorExit(MEM_ERROR, __local_name, errno, strerror(errno));
     }
 
-
-    /* Initializing structure */
-    keys->keyentries = NULL;
+    /* Initialize structure */
+    os_calloc(1, sizeof(keyentry*), keys->keyentries);
     keys->keysize = 0;
 
+    /* Zero the buffers */
+    __memclear(id, name, ip, key, KEYSIZE + 1);
+    memset(buffer, '\0', OS_BUFFER_SIZE + 1);
 
-    /* Zeroing the buffers */
-    __memclear(id, name, ip, key, KEYSIZE +1);
-    memset(buffer, '\0', OS_BUFFER_SIZE +1);
-
-
-    /* Reading each line.
-     * lines are divided as "id name ip key"
-     */
-    while(fgets(buffer, OS_BUFFER_SIZE, fp) != NULL)
-    {
+    /* Read each line. Lines are divided as "id name ip key" */
+    while (fgets(buffer, OS_BUFFER_SIZE, fp) != NULL) {
         char *tmp_str;
         char *valid_str;
 
-        if((buffer[0] == '#') || (buffer[0] == ' '))
+        if ((buffer[0] == '#') || (buffer[0] == ' ')) {
             continue;
+        }
 
-
-        /* Getting ID */
+        /* Get ID */
         valid_str = buffer;
         tmp_str = strchr(buffer, ' ');
-        if(!tmp_str)
-        {
+        if (!tmp_str) {
             merror(INVALID_KEY, __local_name, buffer);
             continue;
         }
 
         *tmp_str = '\0';
         tmp_str++;
-        strncpy(id, valid_str, KEYSIZE -1);
+        strncpy(id, valid_str, KEYSIZE - 1);
 
-        /* Removed entry. */
-        if(*tmp_str == '#')
-        {
+        /* Removed entry */
+        if (*tmp_str == '#') {
             continue;
         }
 
-        /* Getting name */
+        /* Get name */
         valid_str = tmp_str;
         tmp_str = strchr(tmp_str, ' ');
-        if(!tmp_str)
-        {
+        if (!tmp_str) {
             merror(INVALID_KEY, __local_name, buffer);
+            continue;
         }
 
         *tmp_str = '\0';
         tmp_str++;
-        strncpy(name, valid_str, KEYSIZE -1);
+        strncpy(name, valid_str, KEYSIZE - 1);
 
-
-        /* Getting ip address */
+        /* Get IP address */
         valid_str = tmp_str;
         tmp_str = strchr(tmp_str, ' ');
-        if(!tmp_str)
-        {
+        if (!tmp_str) {
             merror(INVALID_KEY, __local_name, buffer);
+            continue;
         }
 
         *tmp_str = '\0';
         tmp_str++;
-        strncpy(ip, valid_str, KEYSIZE -1);
+        strncpy(ip, valid_str, KEYSIZE - 1);
 
-
-        /* Getting key */
+        /* Get key */
         valid_str = tmp_str;
         tmp_str = strchr(tmp_str, '\n');
-        if(tmp_str)
-        {
+        if (tmp_str) {
             *tmp_str = '\0';
         }
 
-        strncpy(key, valid_str, KEYSIZE -1);
-
+        strncpy(key, valid_str, KEYSIZE - 1);
 
-        /* Generating the key hash */
+        /* Generate the key hash */
         __chash(keys, id, name, ip, key);
 
+        /* Clear the memory */
+        __memclear(id, name, ip, key, KEYSIZE + 1);
 
-        /* Clearing the memory */
-        __memclear(id, name, ip, key, KEYSIZE +1);
-
-
-        /* Checking for maximum agent size */
-        if(keys->keysize >= (MAX_AGENTS -2))
-        {
-            merror(AG_MAX_ERROR, __local_name, MAX_AGENTS -2);
+        /* Check for maximum agent size */
+        if (keys->keysize >= (MAX_AGENTS - 2)) {
+            merror(AG_MAX_ERROR, __local_name, MAX_AGENTS - 2);
             ErrorExit(CONFIG_ERROR, __local_name, KEYS_FILE);
         }
 
         continue;
     }
 
-
-    /* Closing key file. */
+    /* Close key file */
     fclose(fp);
 
+    /* Clear one last time before leaving */
+    __memclear(id, name, ip, key, KEYSIZE + 1);
 
-    /* clear one last time before leaving */
-    __memclear(id, name, ip, key, KEYSIZE +1);         
-
-
-    /* Checking if there is any agent available */
-    if(keys->keysize == 0)
-    {
-        ErrorExit(NO_REM_CONN, __local_name);
+    /* Check if there are any agents available */
+    if (keys->keysize == 0) {
+        merror(NO_CLIENT_KEYS, __local_name);
+        if (!pass_empty_keyfile) {
+            exit(1);
+        }
     }
 
-
-    /* Adding additional entry for sender == keysize */
+    /* Add additional entry for sender == keysize */
     os_calloc(1, sizeof(keyentry), keys->keyentries[keys->keysize]);
 
-
     return;
 }
 
-
-/* void __keysfree()
- * Frees the auth keys.
- */
+/* Free the auth keys */
 void OS_FreeKeys(keystore *keys)
 {
-    int i = 0;
-    int _keysize = 0;
-    void *hashid;
-    void *haship;
+    unsigned int i = 0;
+    unsigned int _keysize = 0;
+    OSHash *hashid;
+    OSHash *haship;
 
     _keysize = keys->keysize;
     hashid = keys->keyhash_id;
     haship = keys->keyhash_ip;
 
-
-    /* Zeroing the entries. */
+    /* Zero the entries */
     keys->keysize = 0;
-    keys->keyhash_id =NULL;
+    keys->keyhash_id = NULL;
     keys->keyhash_ip = NULL;
 
-
-    /* Sleeping to give time to other threads to stop using them. */
+    /* Sleep to give time to other threads to stop using them */
     sleep(1);
 
-
-    /* Freeing the hashes */
+    /* Free the hashes */
     OSHash_Free(hashid);
     OSHash_Free(haship);
 
-
-    for(i = 0; i<= _keysize; i++)
-    {
-        if(keys->keyentries[i])
-        {
-            if(keys->keyentries[i]->ip)
-            {
+    for (i = 0; i <= _keysize; i++) {
+        if (keys->keyentries[i]) {
+            if (keys->keyentries[i]->ip) {
                 free(keys->keyentries[i]->ip->ip);
                 free(keys->keyentries[i]->ip);
             }
 
-            if(keys->keyentries[i]->id)
+            if (keys->keyentries[i]->id) {
                 free(keys->keyentries[i]->id);
+            }
 
-            if(keys->keyentries[i]->key)
+            if (keys->keyentries[i]->key) {
                 free(keys->keyentries[i]->key);
+            }
 
-            if(keys->keyentries[i]->name)
+            if (keys->keyentries[i]->name) {
                 free(keys->keyentries[i]->name);
+            }
 
-            /* Closing counter */
-            if(keys->keyentries[i]->fp)
+            /* Close counter */
+            if (keys->keyentries[i]->fp) {
                 fclose(keys->keyentries[i]->fp);
+            }
 
             free(keys->keyentries[i]);
             keys->keyentries[i] = NULL;
         }
     }
 
-    /* Freeing structure */
+    /* Free structure */
     free(keys->keyentries);
     keys->keyentries = NULL;
     keys->keysize = 0;
 }
 
-
-/* int OS_CheckUpdateKeys(keystore *keys)
- * Checks if key changed.
- */
-int OS_CheckUpdateKeys(keystore *keys)
+/* Check if key changed */
+int OS_CheckUpdateKeys(const keystore *keys)
 {
-    if(keys->file_change !=  File_DateofChange(KEYS_FILE))
-    {
-        return(1);
+    if (keys->file_change !=  File_DateofChange(KEYS_FILE)) {
+        return (1);
     }
-    return(0);
+    return (0);
 }
 
-
-/* OS_UpdateKeys(keystore *keys)
- * Update the keys if changed.
- */
+/* Update the keys if changed */
 int OS_UpdateKeys(keystore *keys)
 {
-    if(keys->file_change !=  File_DateofChange(KEYS_FILE))
-    {
+    if (keys->file_change !=  File_DateofChange(KEYS_FILE)) {
         merror(ENCFILE_CHANGED, __local_name);
         debug1("%s: DEBUG: Freekeys", __local_name);
 
         OS_FreeKeys(keys);
         debug1("%s: DEBUG: OS_ReadKeys", __local_name);
 
-        /* Reading keys */
+        /* Read keys */
         verbose(ENC_READ, __local_name);
 
-
         OS_ReadKeys(keys);
         debug1("%s: DEBUG: OS_StartCounter", __local_name);
 
         OS_StartCounter(keys);
         debug1("%s: DEBUG: OS_UpdateKeys completed", __local_name);
 
-        return(1);
+        return (1);
     }
-    return(0);
+    return (0);
 }
 
-
-/* OS_IsAllowedIP()
- * Checks if an IP address is allowed to connect.
- */
-int OS_IsAllowedIP(keystore *keys, char *srcip)
+/* Check if an IP address is allowed to connect */
+int OS_IsAllowedIP(keystore *keys, const char *srcip)
 {
     keyentry *entry;
 
-    if(srcip == NULL)
-        return(-1);
+    if (srcip == NULL) {
+        return (-1);
+    }
 
-    entry = OSHash_Get(keys->keyhash_ip, srcip);
-    if(entry)
-    {
-        return(entry->keyid);
+    entry = (keyentry *) OSHash_Get(keys->keyhash_ip, srcip);
+    if (entry) {
+        return ((int)entry->keyid);
     }
 
-    return(-1);
+    return (-1);
 }
 
-
-/* int OS_IsAllowedName
- * Checks if the agent name is valid.
- */
-int OS_IsAllowedName(keystore *keys, char *name)
+/* Check if the agent name is valid */
+int OS_IsAllowedName(const keystore *keys, const char *name)
 {
-    int i = 0;
+    unsigned int i = 0;
 
-    for(i = 0; i < keys->keysize; i++)
-    {
-        if(strcmp(keys->keyentries[i]->name, name) == 0)
-            return(i);
+    for (i = 0; i < keys->keysize; i++) {
+        if (strcmp(keys->keyentries[i]->name, name) == 0) {
+            return ((int)i);
+        }
     }
 
-    return(-1);
+    return (-1);
 }
 
-
-/* OS_IsAllowedID
- */
-int OS_IsAllowedID(keystore *keys, char *id)
+int OS_IsAllowedID(keystore *keys, const char *id)
 {
     keyentry *entry;
 
-    if(id == NULL)
-        return(-1);
+    if (id == NULL) {
+        return (-1);
+    }
 
-    entry = OSHash_Get(keys->keyhash_id, id);
-    if(entry)
-    {
-        return(entry->keyid);
+    entry = (keyentry *) OSHash_Get(keys->keyhash_id, id);
+    if (entry) {
+        return ((int)entry->keyid);
     }
-    return(-1);
+    return (-1);
 }
 
 
-/* int OS_IsAllowedDynamicID -- Used for dynamic ip addresses.
- */
-int OS_IsAllowedDynamicID(keystore *keys, char *id, char *srcip)
+/* Used for dynamic IP addresses */
+int OS_IsAllowedDynamicID(keystore *keys, const char *id, const char *srcip)
 {
     keyentry *entry;
 
-    if(id == NULL)
-        return(-1);
+    if (id == NULL) {
+        return (-1);
+    }
 
-    entry = OSHash_Get(keys->keyhash_id, id);
-    if(entry)
-    {
-        if(OS_IPFound(srcip, entry->ip))
-        {
-            return(entry->keyid);
+    entry = (keyentry *) OSHash_Get(keys->keyhash_id, id);
+    if (entry) {
+        if (OS_IPFound(srcip, entry->ip)) {
+            return ((int)entry->keyid);
         }
     }
 
-    return(-1);
+    return (-1);
 }
-
-
-/* EOF */
+ /* Configure to pass if keys file is empty */
+ void OS_PassEmptyKeyfile() {
+     pass_empty_keyfile = 1;
+ }