pacemaker  1.1.15-e174ec8
Scalable High-Availability cluster resource manager
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
cib_secrets.c
Go to the documentation of this file.
1 /*
2  * cib_secrets.c
3  *
4  * Author: Dejan Muhamedagic <dejan@suse.de>
5  * Copyright (c) 2011 SUSE, Attachmate
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This software is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21 
22 #include <crm_internal.h>
23 
24 #include <unistd.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <ctype.h>
29 #include <errno.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <time.h>
33 
34 #include <glib.h>
35 
36 #include <crm/common/util.h>
37 #include <crm/common/cib_secrets.h>
38 
39 static int do_replace_secret_params(char *rsc_id, GHashTable *params, gboolean from_legacy_dir);
40 static int is_magic_value(char *p);
41 static int check_md5_hash(char *hash, char *value);
42 static void add_secret_params(gpointer key, gpointer value, gpointer user_data);
43 static char *read_local_file(char *local_file);
44 
45 #define MAX_VALUE_LEN 255
46 #define MAGIC "lrm://"
47 
48 static int
49 is_magic_value(char *p)
50 {
51  return !strcmp(p, MAGIC);
52 }
53 
54 static int
55 check_md5_hash(char *hash, char *value)
56 {
57  int rc = FALSE;
58  char *hash2 = NULL;
59 
60  hash2 = crm_md5sum(value);
61  crm_debug("hash: %s, calculated hash: %s", hash, hash2);
62  if (safe_str_eq(hash, hash2)) {
63  rc = TRUE;
64  }
65 
66  free(hash2);
67  return rc;
68 }
69 
70 static char *
71 read_local_file(char *local_file)
72 {
73  FILE *fp = fopen(local_file, "r");
74  char buf[MAX_VALUE_LEN+1];
75  char *p;
76 
77  if (!fp) {
78  if (errno != ENOENT) {
79  crm_perror(LOG_ERR, "cannot open %s" , local_file);
80  }
81  return NULL;
82  }
83 
84  if (!fgets(buf, MAX_VALUE_LEN, fp)) {
85  crm_perror(LOG_ERR, "cannot read %s", local_file);
86  return NULL;
87  }
88 
89  /* strip white space */
90  for (p = buf+strlen(buf)-1; p >= buf && isspace(*p); p--)
91  ;
92  *(p+1) = '\0';
93  return strdup(buf);
94 }
95 
96 /*
97  * returns 0 on success or no replacements necessary
98  * returns -1 if replacement failed for whatever reasone
99  */
100 
101 int
102 replace_secret_params(char *rsc_id, GHashTable *params)
103 {
104  if (do_replace_secret_params(rsc_id, params, FALSE) < 0
105  && do_replace_secret_params(rsc_id, params, TRUE) < 0) {
106  return -1;
107  }
108 
109  return 0;
110 }
111 
112 static int
113 do_replace_secret_params(char *rsc_id, GHashTable *params, gboolean from_legacy_dir)
114 {
115  char local_file[FILENAME_MAX+1], *start_pname;
116  char hash_file[FILENAME_MAX+1], *hash;
117  GList *secret_params = NULL, *l;
118  char *key, *pvalue, *secret_value;
119  int rc = 0;
120  const char *dir_prefix = NULL;
121 
122  if (params == NULL) {
123  return 0;
124  }
125 
126  if (from_legacy_dir) {
127  dir_prefix = LRM_LEGACY_CIBSECRETS_DIR;
128 
129  } else {
130  dir_prefix = LRM_CIBSECRETS_DIR;
131  }
132 
133  /* secret_params could be cached with the resource;
134  * there are also parameters sent with operations
135  * which cannot be cached
136  */
137  g_hash_table_foreach(params, add_secret_params, &secret_params);
138  if (!secret_params) { /* none found? */
139  return 0;
140  }
141 
142  crm_debug("replace secret parameters for resource %s", rsc_id);
143 
144  if (snprintf(local_file, FILENAME_MAX,
145  "%s/%s/", dir_prefix, rsc_id) > FILENAME_MAX) {
146  crm_err("filename size exceeded for resource %s", rsc_id);
147  return -1;
148  }
149  start_pname = local_file + strlen(local_file);
150 
151  for (l = g_list_first(secret_params); l; l = g_list_next(l)) {
152  key = (char *)(l->data);
153  pvalue = g_hash_table_lookup(params, key);
154  if (!pvalue) { /* this cannot really happen */
155  crm_err("odd, no parameter %s for rsc %s found now", key, rsc_id);
156  continue;
157  }
158 
159  if ((strlen(key) + strlen(local_file)) >= FILENAME_MAX-2) {
160  crm_err("%d: parameter name %s too big", key);
161  rc = -1;
162  continue;
163  }
164 
165  strcpy(start_pname, key);
166  secret_value = read_local_file(local_file);
167  if (!secret_value) {
168  if (from_legacy_dir == FALSE) {
169  crm_debug("secret for rsc %s parameter %s not found in %s. "
170  "will try "LRM_LEGACY_CIBSECRETS_DIR, rsc_id, key, dir_prefix);
171 
172  } else {
173  crm_err("secret for rsc %s parameter %s not found in %s",
174  rsc_id, key, dir_prefix);
175  }
176  rc = -1;
177  continue;
178  }
179 
180  strcpy(hash_file, local_file);
181  if (strlen(hash_file) + 5 > FILENAME_MAX) {
182  crm_err("cannot build such a long name "
183  "for the sign file: %s.sign", hash_file);
184  free(secret_value);
185  rc = -1;
186  continue;
187 
188  } else {
189  strncat(hash_file, ".sign", 5);
190  hash = read_local_file(hash_file);
191  if (hash == NULL) {
192  crm_err("md5 sum for rsc %s parameter %s "
193  "cannot be read from %s", rsc_id, key, hash_file);
194  free(secret_value);
195  rc = -1;
196  continue;
197 
198  } else if (!check_md5_hash(hash, secret_value)) {
199  crm_err("md5 sum for rsc %s parameter %s "
200  "does not match", rsc_id, key);
201  free(secret_value);
202  free(hash);
203  rc = -1;
204  continue;
205  }
206  free(hash);
207  }
208  g_hash_table_replace(params, strdup(key), secret_value);
209  }
210  g_list_free(secret_params);
211  return rc;
212 }
213 
214 static void
215 add_secret_params(gpointer key, gpointer value, gpointer user_data)
216 {
217  GList **lp = (GList **)user_data;
218 
219  if (is_magic_value((char *)value)) {
220  *lp = g_list_append(*lp, (char *)key);
221  }
222 }
#define MAGIC
Definition: cib_secrets.c:46
#define crm_debug(fmt, args...)
Definition: logging.h:253
int replace_secret_params(char *rsc_id, GHashTable *params)
Definition: cib_secrets.c:102
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:45
char * crm_md5sum(const char *buffer)
Definition: utils.c:2374
#define safe_str_eq(a, b)
Definition: util.h:74