root/lib/common/cib_secrets.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. is_magic_value
  2. check_md5_hash
  3. read_local_file
  4. replace_secret_params
  5. do_replace_secret_params
  6. add_secret_params

   1 /*
   2  * Copyright (c) 2011 SUSE, Attachmate
   3  * Author: Dejan Muhamedagic <dejan@suse.de>
   4  *
   5  * This source code is licensed under the GNU Lesser General Public License
   6  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
   7  */
   8 
   9 #include <crm_internal.h>
  10 
  11 #include <unistd.h>
  12 #include <stdlib.h>
  13 #include <stdio.h>
  14 #include <string.h>
  15 #include <ctype.h>
  16 #include <errno.h>
  17 #include <sys/types.h>
  18 #include <sys/stat.h>
  19 #include <time.h>
  20 
  21 #include <glib.h>
  22 
  23 #include <crm/common/util.h>
  24 #include <crm/common/cib_secrets.h>
  25 
  26 static int do_replace_secret_params(char *rsc_id, GHashTable *params, gboolean from_legacy_dir);
  27 static int is_magic_value(char *p);
  28 static int check_md5_hash(char *hash, char *value);
  29 static void add_secret_params(gpointer key, gpointer value, gpointer user_data);
  30 static char *read_local_file(char *local_file);
  31 
  32 #define MAX_VALUE_LEN 255
  33 #define MAGIC "lrm://"
  34 
  35 static int
  36 is_magic_value(char *p)
     /* [previous][next][first][last][top][bottom][index][help] */
  37 {
  38     return !strcmp(p, MAGIC);
  39 }
  40 
  41 static int
  42 check_md5_hash(char *hash, char *value)
     /* [previous][next][first][last][top][bottom][index][help] */
  43 {
  44     int rc = FALSE;
  45     char *hash2 = NULL;
  46 
  47     hash2 = crm_md5sum(value);
  48     crm_debug("hash: %s, calculated hash: %s", hash, hash2);
  49     if (safe_str_eq(hash, hash2)) {
  50         rc = TRUE;
  51     }
  52 
  53     free(hash2);
  54     return rc;
  55 }
  56 
  57 static char *
  58 read_local_file(char *local_file)
     /* [previous][next][first][last][top][bottom][index][help] */
  59 {
  60     FILE *fp = fopen(local_file, "r");
  61     char buf[MAX_VALUE_LEN+1];
  62     char *p;
  63 
  64     if (!fp) {
  65         if (errno != ENOENT) {
  66             crm_perror(LOG_ERR, "cannot open %s" , local_file);
  67         }
  68         return NULL;
  69     }
  70 
  71     if (!fgets(buf, MAX_VALUE_LEN, fp)) {
  72         crm_perror(LOG_ERR, "cannot read %s", local_file);
  73         return NULL;
  74     }
  75 
  76     /* strip white space */
  77     for (p = buf+strlen(buf)-1; p >= buf && isspace(*p); p--)
  78                 ;
  79     *(p+1) = '\0';
  80     return strdup(buf);
  81 }
  82 
  83 /*
  84  * returns 0 on success or no replacements necessary
  85  * returns -1 if replacement failed for whatever reasone
  86  */
  87 
  88 int
  89 replace_secret_params(char *rsc_id, GHashTable *params)
     /* [previous][next][first][last][top][bottom][index][help] */
  90 {
  91     if (do_replace_secret_params(rsc_id, params, FALSE) < 0
  92         && do_replace_secret_params(rsc_id, params, TRUE) < 0) {
  93         return -1;
  94     }
  95 
  96     return 0;
  97 }
  98 
  99 static int
 100 do_replace_secret_params(char *rsc_id, GHashTable *params, gboolean from_legacy_dir)
     /* [previous][next][first][last][top][bottom][index][help] */
 101 {
 102     char local_file[FILENAME_MAX+1], *start_pname;
 103     char hash_file[FILENAME_MAX+1], *hash;
 104     GList *secret_params = NULL, *l;
 105     char *key, *pvalue, *secret_value;
 106     int rc = 0;
 107     const char *dir_prefix = NULL;
 108 
 109     if (params == NULL) {
 110         return 0;
 111     }
 112 
 113     if (from_legacy_dir) {
 114         dir_prefix = LRM_LEGACY_CIBSECRETS_DIR;
 115 
 116     } else {
 117         dir_prefix = LRM_CIBSECRETS_DIR;
 118     }
 119 
 120     /* secret_params could be cached with the resource;
 121      * there are also parameters sent with operations
 122      * which cannot be cached
 123      */
 124     g_hash_table_foreach(params, add_secret_params, &secret_params);
 125     if (!secret_params) { /* none found? */
 126         return 0;
 127     }
 128 
 129     crm_debug("replace secret parameters for resource %s", rsc_id);
 130 
 131     if (snprintf(local_file, FILENAME_MAX,
 132         "%s/%s/", dir_prefix, rsc_id) > FILENAME_MAX) {
 133         crm_err("filename size exceeded for resource %s", rsc_id);
 134         return -1;
 135     }
 136     start_pname = local_file + strlen(local_file);
 137 
 138     for (l = g_list_first(secret_params); l; l = g_list_next(l)) {
 139         key = (char *)(l->data);
 140         pvalue = g_hash_table_lookup(params, key);
 141         if (!pvalue) { /* this cannot really happen */
 142             crm_err("odd, no parameter %s for rsc %s found now", key, rsc_id);
 143             continue;
 144         }
 145 
 146         if ((strlen(key) + strlen(local_file)) >= FILENAME_MAX-2) {
 147             crm_err("%d: parameter name %s too big", key);
 148             rc = -1;
 149             continue;
 150         }
 151 
 152         strcpy(start_pname, key);
 153         secret_value = read_local_file(local_file);
 154         if (!secret_value) {
 155             if (from_legacy_dir == FALSE) {
 156                 crm_debug("secret for rsc %s parameter %s not found in %s. "
 157                           "will try "LRM_LEGACY_CIBSECRETS_DIR, rsc_id, key, dir_prefix);
 158 
 159             } else {
 160                 crm_err("secret for rsc %s parameter %s not found in %s",
 161                         rsc_id, key, dir_prefix);
 162             }
 163             rc = -1;
 164             continue;
 165         }
 166 
 167         strcpy(hash_file, local_file);
 168         if (strlen(hash_file) + 5 > FILENAME_MAX) {
 169             crm_err("cannot build such a long name "
 170                     "for the sign file: %s.sign", hash_file);
 171             free(secret_value);
 172             rc = -1;
 173             continue;
 174 
 175         } else {
 176             strncat(hash_file, ".sign", 5);
 177             hash = read_local_file(hash_file);
 178             if (hash == NULL) {
 179                 crm_err("md5 sum for rsc %s parameter %s "
 180                         "cannot be read from %s", rsc_id, key, hash_file);
 181                 free(secret_value);
 182                 rc = -1;
 183                 continue;
 184 
 185             } else if (!check_md5_hash(hash, secret_value)) {
 186                 crm_err("md5 sum for rsc %s parameter %s "
 187                         "does not match", rsc_id, key);
 188                 free(secret_value);
 189                 free(hash);
 190                 rc = -1;
 191                 continue;
 192             }
 193             free(hash);
 194         }
 195         g_hash_table_replace(params, strdup(key), secret_value);
 196     }
 197     g_list_free(secret_params);
 198     return rc;
 199 }
 200 
 201 static void
 202 add_secret_params(gpointer key, gpointer value, gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 203 {
 204     GList **lp = (GList **)user_data;
 205 
 206     if (is_magic_value((char *)value)) {
 207         *lp = g_list_append(*lp, (char *)key);
 208     }
 209 }

/* [previous][next][first][last][top][bottom][index][help] */