Now wd_authkey uses the HMAC SHA-256 hashing.
return 1;
}
-static void
-bytesToHex(uint8 b[16], char *s)
+void
+bytesToHex(char *b, int len, char *s)
{
static const char *hex = "0123456789abcdef";
int q,
w;
- for (q = 0, w = 0; q < 16; q++)
+ for (q = 0, w = 0; q < len; q++)
{
s[w++] = hex[(b[q] >> 4) & 0x0F];
s[w++] = hex[b[q] & 0x0F];
if (!calculateDigestFromBuffer((uint8 *) buff, len, sum))
return 0; /* failed */
- bytesToHex(sum, hexsum);
+ bytesToHex((char *)sum, 16, hexsum);
return 1; /* success */
}
#define MAX_USER_NAME_LEN 128
#define MD5_PASSWD_LEN 32
+#define WD_AUTH_HASH_LEN 64
+
extern int pool_md5_hash(const void *buff, size_t len, char *hexsum);
extern int pool_md5_encrypt(const char *passwd, const char *salt, size_t salt_len, char *buf);
-
+extern void bytesToHex(char *b, int len, char *s);
#endif
g_cluster.remoteNodes[i].pgpool_port = pool_config->wd_remote_nodes.wd_remote_node_info[i].pgpool_port;
strcpy(g_cluster.remoteNodes[i].hostname, pool_config->wd_remote_nodes.wd_remote_node_info[i].hostname);
g_cluster.remoteNodes[i].delegate_ip[0] = '\0'; /*this will be populated by remote node*/
-
+
ereport(LOG,
(errmsg("watchdog remote node:%d on %s:%d",i,g_cluster.remoteNodes[i].hostname, g_cluster.remoteNodes[i].wd_port)));
}
clear_command_node_result(&g_cluster.currentCommand.nodeResults[i]);
}
wd_initialize_monitoring_interfaces();
+ if (g_cluster.ipc_auth_needed)
+ {
+#ifndef USE_SSL
+ ereport(LOG,
+ (errmsg("watchdog is configured to use authentication, but pgpool-II is built without SSL support"),
+ errdetail("The authentication method used by pgpool-II without the SSL support is known to be weak")));
+#endif
+ }
+
}
static void clear_command_node_result(WDCommandNodeResult* nodeResult)
static WDPacketData* get_addnode_message(void)
{
- char authhash[(MD5_PASSWD_LEN+1)*2];
+ char authhash[WD_AUTH_HASH_LEN + 1];
WDPacketData *message = get_empty_packet();
bool include_hash = get_authhash_for_node(g_cluster.localNode, authhash);
char *json_data = get_watchdog_node_info_json(g_cluster.localNode, include_hash?authhash:NULL);
static WDPacketData* get_mynode_info_message(WDPacketData* replyFor)
{
- char authhash[(MD5_PASSWD_LEN+1)*2];
+ char authhash[WD_AUTH_HASH_LEN + 1];
WDPacketData *message = get_empty_packet();
bool include_hash = get_authhash_for_node(g_cluster.localNode, authhash);
char *json_data = get_watchdog_node_info_json(g_cluster.localNode, include_hash?authhash:NULL);
{
char *authkey = NULL;
WatchdogNode* tempNode = parse_node_info_message(pkt, &authkey);
+ if (tempNode == NULL)
+ {
+ ereport(WARNING,
+ (errmsg("node \"%s\" sent an invalid node info message",wdNode->nodeName)));
+ break;
+ }
wdNode->state = tempNode->state;
wdNode->startup_time.tv_sec = tempNode->startup_time.tv_sec;
wdNode->wd_priority = tempNode->wd_priority;
{
if (strlen(pool_config->wd_authkey))
{
- char calculated_authhash[(MD5_PASSWD_LEN+1)*2];
+ char calculated_authhash[WD_AUTH_HASH_LEN + 1];
char nodeStr[WD_MAX_PACKET_STRING];
int len = snprintf(nodeStr, WD_MAX_PACKET_STRING, "state=%d tv_sec=%ld wd_port=%d",
char from[WD_MAX_HOST_NAMELEN];
int from_pgpool_port;
struct timeval send_time;
- char hash[(MD5_PASSWD_LEN+1)*2];
+ char hash[WD_AUTH_HASH_LEN + 1];
} WdHbPacket;
struct timeval tv;
char from[WD_MAX_HOST_NAMELEN];
int from_pgpool_port;
- char buf[(MD5_PASSWD_LEN+1)*2];
+ char buf[WD_AUTH_HASH_LEN + 1];
char pack_str[WD_MAX_PACKET_STRING];
int pack_str_len;
sigjmp_buf local_sigjmp_buf;
}
+#ifdef USE_SSL
+/* HMAC SHA-256*/
+static void calculate_hmac_sha256(const char *data, int len, char *buf)
+{
+ char* key = pool_config->wd_authkey;
+ char str[WD_AUTH_HASH_LEN/2];
+
+ unsigned int res_len = WD_AUTH_HASH_LEN;
+
+ HMAC_CTX ctx;
+ HMAC_CTX_init(&ctx);
+ HMAC_Init_ex(&ctx, key, strlen(key), EVP_sha256(), NULL);
+ HMAC_Update(&ctx, (unsigned char*)data, len);
+ HMAC_Final(&ctx, (unsigned char*)str, &res_len);
+ HMAC_CTX_cleanup(&ctx);
+ bytesToHex(str,32,buf);
+ buf[WD_AUTH_HASH_LEN] = '\0';
+}
+void
+wd_calc_hash(const char *str, int len, char *buf)
+{
+ calculate_hmac_sha256(str, len, buf);
+}
+#else
/* calculate hash for authentication using packet contents */
void
wd_calc_hash(const char *str, int len, char *buf)
size_t pass_len;
size_t username_len;
size_t authkey_len;
-
+ char tmp_buf[(MD5_PASSWD_LEN+1)*2];
/* use first half of authkey as username, last half as password */
authkey_len = strlen(pool_config->wd_authkey);
username_len = authkey_len / 2;
pass_len = authkey_len - username_len;
if ( snprintf(username, username_len + 1, "%s", pool_config->wd_authkey) < 0
- || snprintf(pass, pass_len + 1, "%s", pool_config->wd_authkey + username_len) < 0)
+ || snprintf(pass, pass_len + 1, "%s", pool_config->wd_authkey + username_len) < 0)
goto wd_calc_hash_error;
/* calculate hash using md5 encrypt */
- if (! pool_md5_encrypt(pass, username, strlen(username), buf + MD5_PASSWD_LEN + 1))
+ if (! pool_md5_encrypt(pass, username, strlen(username), tmp_buf + MD5_PASSWD_LEN + 1))
goto wd_calc_hash_error;
buf[(MD5_PASSWD_LEN+1)*2-1] = '\0';
- if (! pool_md5_encrypt(buf+MD5_PASSWD_LEN+1, str, len, buf))
+ if (! pool_md5_encrypt(tmp_buf+MD5_PASSWD_LEN+1, str, len, tmp_buf))
goto wd_calc_hash_error;
+
+ memcpy(buf, tmp_buf, MD5_PASSWD_LEN);
buf[MD5_PASSWD_LEN] = '\0';
return;
buf[0] = '\0';
return;
}
+#endif
/*
* string_replace: