pacemaker  2.0.2-debe490
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 is_magic_value(char *p);
27 static int check_md5_hash(char *hash, char *value);
28 static void add_secret_params(gpointer key, gpointer value, gpointer user_data);
29 static char *read_local_file(char *local_file);
30 
31 #define MAX_VALUE_LEN 255
32 #define MAGIC "lrm://"
33 
34 static int
35 is_magic_value(char *p)
36 {
37  return !strcmp(p, MAGIC);
38 }
39 
40 static int
41 check_md5_hash(char *hash, char *value)
42 {
43  int rc = FALSE;
44  char *hash2 = NULL;
45 
46  hash2 = crm_md5sum(value);
47  crm_debug("hash: %s, calculated hash: %s", hash, hash2);
48  if (safe_str_eq(hash, hash2)) {
49  rc = TRUE;
50  }
51 
52  free(hash2);
53  return rc;
54 }
55 
56 static char *
57 read_local_file(char *local_file)
58 {
59  FILE *fp = fopen(local_file, "r");
60  char buf[MAX_VALUE_LEN+1];
61  char *p;
62 
63  if (!fp) {
64  if (errno != ENOENT) {
65  crm_perror(LOG_ERR, "cannot open %s" , local_file);
66  }
67  return NULL;
68  }
69 
70  if (!fgets(buf, MAX_VALUE_LEN, fp)) {
71  crm_perror(LOG_ERR, "cannot read %s", local_file);
72  fclose(fp);
73  return NULL;
74  }
75  fclose(fp);
76 
77  /* strip white space */
78  for (p = buf+strlen(buf)-1; p >= buf && isspace(*p); p--)
79  ;
80  *(p+1) = '\0';
81  return strdup(buf);
82 }
83 
84 /*
85  * returns 0 on success or no replacements necessary
86  * returns -1 if replacement failed for whatever reasone
87  */
88 
89 int
90 replace_secret_params(const char *rsc_id, GHashTable *params)
91 {
92  char local_file[FILENAME_MAX+1], *start_pname;
93  char hash_file[FILENAME_MAX+1], *hash;
94  GList *secret_params = NULL, *l;
95  char *key, *pvalue, *secret_value;
96  int rc = 0;
97 
98  if (params == NULL) {
99  return 0;
100  }
101 
102  /* secret_params could be cached with the resource;
103  * there are also parameters sent with operations
104  * which cannot be cached
105  */
106  g_hash_table_foreach(params, add_secret_params, &secret_params);
107  if (!secret_params) { /* none found? */
108  return 0;
109  }
110 
111  crm_debug("replace secret parameters for resource %s", rsc_id);
112 
113  if (snprintf(local_file, FILENAME_MAX, LRM_CIBSECRETS_DIR "/%s/", rsc_id)
114  > FILENAME_MAX) {
115  crm_err("filename size exceeded for resource %s", rsc_id);
116  return -1;
117  }
118  start_pname = local_file + strlen(local_file);
119 
120  for (l = g_list_first(secret_params); l; l = g_list_next(l)) {
121  key = (char *)(l->data);
122  pvalue = g_hash_table_lookup(params, key);
123  if (!pvalue) { /* this cannot really happen */
124  crm_err("odd, no parameter %s for rsc %s found now", key, rsc_id);
125  continue;
126  }
127 
128  if ((strlen(key) + strlen(local_file)) >= FILENAME_MAX-2) {
129  crm_err("%d: parameter name %s too big", key);
130  rc = -1;
131  continue;
132  }
133 
134  strcpy(start_pname, key);
135  secret_value = read_local_file(local_file);
136  if (!secret_value) {
137  crm_err("secret for rsc %s parameter %s not found in %s",
138  rsc_id, key, LRM_CIBSECRETS_DIR);
139  rc = -1;
140  continue;
141  }
142 
143  strcpy(hash_file, local_file);
144  if (strlen(hash_file) + 5 > FILENAME_MAX) {
145  crm_err("cannot build such a long name "
146  "for the sign file: %s.sign", hash_file);
147  free(secret_value);
148  rc = -1;
149  continue;
150 
151  } else {
152  strncat(hash_file, ".sign", 5);
153  hash = read_local_file(hash_file);
154  if (hash == NULL) {
155  crm_err("md5 sum for rsc %s parameter %s "
156  "cannot be read from %s", rsc_id, key, hash_file);
157  free(secret_value);
158  rc = -1;
159  continue;
160 
161  } else if (!check_md5_hash(hash, secret_value)) {
162  crm_err("md5 sum for rsc %s parameter %s "
163  "does not match", rsc_id, key);
164  free(secret_value);
165  free(hash);
166  rc = -1;
167  continue;
168  }
169  free(hash);
170  }
171  g_hash_table_replace(params, strdup(key), secret_value);
172  }
173  g_list_free(secret_params);
174  return rc;
175 }
176 
177 static void
178 add_secret_params(gpointer key, gpointer value, gpointer user_data)
179 {
180  GList **lp = (GList **)user_data;
181 
182  if (is_magic_value((char *)value)) {
183  *lp = g_list_append(*lp, (char *)key);
184  }
185 }
#define MAGIC
Definition: cib_secrets.c:32
#define crm_debug(fmt, args...)
Definition: logging.h:245
Utility functions.
int replace_secret_params(const char *rsc_id, GHashTable *params)
Definition: cib_secrets.c:90
#define crm_perror(level, fmt, args...)
Log a system error message.
Definition: logging.h:218
#define crm_err(fmt, args...)
Definition: logging.h:240
#define MAX_VALUE_LEN
Definition: cib_secrets.c:31
char * crm_md5sum(const char *buffer)
Definition: utils.c:1153
#define safe_str_eq(a, b)
Definition: util.h:59