pacemaker  1.1.18-7fdfbbe
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cib_secrets.c
Go to the documentation of this file.
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)
37 {
38  return !strcmp(p, MAGIC);
39 }
40 
41 static int
42 check_md5_hash(char *hash, char *value)
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)
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)
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)
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)
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 }
int replace_secret_params(char *rsc_id, GHashTable *params)
Definition: cib_secrets.c:89
#define MAGIC
Definition: cib_secrets.c:33
#define crm_debug(fmt, args...)
Definition: logging.h:253
Utility functions.
#define crm_perror(level, fmt, args...)
Log a system error message.
Definition: logging.h:226
#define crm_err(fmt, args...)
Definition: logging.h:248
#define MAX_VALUE_LEN
Definition: cib_secrets.c:32
char * crm_md5sum(const char *buffer)
Definition: utils.c:1424
#define safe_str_eq(a, b)
Definition: util.h:72