X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fnut.c;h=2173af9b5fe3c211bce339378bf60dfe934ebce2;hb=267bbc64779f9c7b32e063aac0df22be61bda6ae;hp=d40e09510c1d7598dadc330ff53c4689576d0885;hpb=d3be3ed7cb69be4a9a256449d4885d4a55399de0;p=collectd.git diff --git a/src/nut.c b/src/nut.c index d40e0951..2173af9b 100644 --- a/src/nut.c +++ b/src/nut.c @@ -54,8 +54,11 @@ static nut_ups_t *upslist_head = NULL; static pthread_mutex_t read_lock = PTHREAD_MUTEX_INITIALIZER; static int read_busy = 0; -static const char *config_keys[] = {"UPS"}; +static const char *config_keys[] = {"UPS", "FORCESSL", "VERIFYPEER", "CAPATH"}; static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); +static int force_ssl = 0; // Initialized to default of 0 (false) +static int verify_peer = 0; // Initialized to default of 0 (false) +static char *ca_path = NULL; static void free_nut_ups_t(nut_ups_t *ups) { if (ups->conn != NULL) { @@ -76,14 +79,14 @@ static int nut_add_ups(const char *name) { ups = calloc(1, sizeof(*ups)); if (ups == NULL) { ERROR("nut plugin: nut_add_ups: calloc failed."); - return (1); + return 1; } status = upscli_splitname(name, &ups->upsname, &ups->hostname, &ups->port); if (status != 0) { ERROR("nut plugin: nut_add_ups: upscli_splitname (%s) failed.", name); free_nut_ups_t(ups); - return (1); + return 1; } if (upslist_head == NULL) @@ -95,14 +98,56 @@ static int nut_add_ups(const char *name) { last->next = ups; } - return (0); + return 0; } /* int nut_add_ups */ +static int nut_force_ssl(const char *value) { + if (strcasecmp(value, "true") == 0) + force_ssl = 1; + else if (strcasecmp(value, "false") == 0) + force_ssl = 0; // Should already be set to 0 from initialization + else { + force_ssl = 0; + WARNING("nut plugin: nut_force_ssl: invalid FORCESSL value " + "found. Defaulting to false."); + } + return 0; +} /* int nut_parse_force_ssl */ + +static int nut_verify_peer(const char *value) { + if (strcasecmp(value, "true") == 0) + verify_peer = 1; + else if (strcasecmp(value, "false") == 0) + verify_peer = 0; // Should already be set to 0 from initialization + else { + verify_peer = 0; + WARNING("nut plugin: nut_verify_peer: invalid VERIFYPEER value " + "found. Defaulting to false."); + } + return 0; +} /* int nut_verify_peer */ + +static int nut_ca_path(const char *value) { + if (value != NULL && strcmp(value, "") != 0) { + ca_path = malloc(strlen(value) + 1); + strncpy(ca_path, value, (strlen(value) + 1)); + } else { + ca_path = NULL; // Should alread be set to NULL from initialization + } + return 0; +} /* int nut_ca_path */ + static int nut_config(const char *key, const char *value) { if (strcasecmp(key, "UPS") == 0) - return (nut_add_ups(value)); + return nut_add_ups(value); + else if (strcasecmp(key, "FORCESSL") == 0) + return nut_force_ssl(value); + else if (strcasecmp(key, "VERIFYPEER") == 0) + return nut_verify_peer(value); + else if (strcasecmp(key, "CAPATH") == 0) + return nut_ca_path(value); else - return (-1); + return -1; } /* int nut_config */ static void nut_submit(nut_ups_t *ups, const char *type, @@ -123,6 +168,119 @@ static void nut_submit(nut_ups_t *ups, const char *type, plugin_dispatch_values(&vl); } /* void nut_submit */ +static int nut_connect(nut_ups_t *ups) { +#if HAVE_UPSCLI_INIT + int status; + int ssl_status; + int ssl_flags; + + if (verify_peer == 1 && force_ssl == 0) { + WARNING("nut plugin: nut_connect: VerifyPeer true but ForceSSL " + "false. Setting ForceSSL to true."); + force_ssl = 1; + } + + if (verify_peer == 1 && ca_path == NULL) { + ERROR("nut plugin: nut_connect: VerifyPeer true but missing " + "CAPath value."); + return -1; + } + + if (verify_peer == 1) { + status = upscli_init(verify_peer, ca_path, NULL, NULL); + + if (status != 1) { + ERROR("nut plugin: nut_connect: upscli_init (%i, %s) failed: %s", + verify_peer, ca_path, upscli_strerror(ups->conn)); + upscli_cleanup(); + return -1; + } + } /* if (verify_peer == 1) */ + + if (verify_peer == 1) + ssl_flags = (UPSCLI_CONN_REQSSL | UPSCLI_CONN_CERTVERIF); + else if (force_ssl == 1) + ssl_flags = UPSCLI_CONN_REQSSL; + else + ssl_flags = UPSCLI_CONN_TRYSSL; + + status = upscli_connect(ups->conn, ups->hostname, ups->port, ssl_flags); + + if (status != 0) { + ERROR("nut plugin: nut_connect: upscli_connect (%s, %i) failed: %s", + ups->hostname, ups->port, upscli_strerror(ups->conn)); + sfree(ups->conn); + upscli_cleanup(); + return -1; + } /* if (status != 0) */ + + INFO("nut plugin: Connection to (%s, %i) established.", ups->hostname, + ups->port); + + // Output INFO or WARNING based on SSL and VERIFICATION + ssl_status = upscli_ssl(ups->conn); // 1 for SSL, 0 for not, -1 for error + if (ssl_status == 1 && verify_peer == 1) { + INFO("nut plugin: Connection is secured with SSL and certificate " + "has been verified."); + } else if (ssl_status == 1) { + INFO("nut plugin: Connection is secured with SSL with no verification " + "of server SSL certificate."); + } else if (ssl_status == 0) { + WARNING("nut plugin: Connection is unsecured (no SSL)."); + } else { + ERROR("nut plugin: nut_connect: upscli_ssl failed: %s", + upscli_strerror(ups->conn)); + sfree(ups->conn); + upscli_cleanup(); + return -1; + } /* if (ssl_status == 1 && verify_peer == 1) */ + return 0; + +#else /* #if HAVE_UPSCLI_INIT */ + int status; + int ssl_status; + int ssl_flags; + + if (verify_peer == 1 || ca_path != NULL) { + WARNING("nut plugin: nut_connect: Dependency libupsclient version " + "insufficient (<2.7) for VerifyPeer support. Ignoring VerifyPeer " + "and CAPath."); + } + + if (force_ssl == 1) + ssl_flags = UPSCLI_CONN_REQSSL; + else + ssl_flags = UPSCLI_CONN_TRYSSL; + + status = upscli_connect(ups->conn, ups->hostname, ups->port, ssl_flags); + + if (status != 0) { + ERROR("nut plugin: nut_connect: upscli_connect (%s, %i) failed: %s", + ups->hostname, ups->port, upscli_strerror(ups->conn)); + sfree(ups->conn); + return -1; + } /* if (status != 0) */ + + INFO("nut plugin: Connection to (%s, %i) established.", ups->hostname, + ups->port); + + // Output INFO or WARNING based on SSL + ssl_status = upscli_ssl(ups->conn); // 1 for SSL, 0 for not, -1 for error + if (ssl_status == 1) { + INFO("nut plugin: Connection is secured with SSL with no verification " + "of server SSL certificate."); + } else if (ssl_status == 0) { + WARNING("nut plugin: Connection is unsecured (no SSL)."); + } else { + ERROR("nut plugin: nut_connect: upscli_ssl failed: %s", + upscli_strerror(ups->conn)); + sfree(ups->conn); + return -1; + } /* if (ssl_status == 1 && verify_peer == 1) */ + return 0; +#endif +} + static int nut_read_one(nut_ups_t *ups) { const char *query[3] = {"VAR", ups->upsname, NULL}; unsigned int query_num = 2; @@ -135,20 +293,13 @@ static int nut_read_one(nut_ups_t *ups) { ups->conn = malloc(sizeof(*ups->conn)); if (ups->conn == NULL) { ERROR("nut plugin: malloc failed."); - return (-1); + return -1; } - status = - upscli_connect(ups->conn, ups->hostname, ups->port, UPSCLI_CONN_TRYSSL); - if (status != 0) { - ERROR("nut plugin: nut_read_one: upscli_connect (%s, %i) failed: %s", - ups->hostname, ups->port, upscli_strerror(ups->conn)); - sfree(ups->conn); - return (-1); - } + status = nut_connect(ups); + if (status == -1) + return -1; - INFO("nut plugin: Connection to (%s, %i) established.", ups->hostname, - ups->port); } /* if (ups->conn == NULL) */ /* nut plugin: nut_read_one: upscli_list_start (adpos) failed: Protocol @@ -159,7 +310,10 @@ static int nut_read_one(nut_ups_t *ups) { ups->upsname, upscli_strerror(ups->conn)); upscli_disconnect(ups->conn); sfree(ups->conn); - return (-1); +#if HAVE_UPSCLI_INIT + upscli_cleanup(); +#endif + return -1; } while ((status = upscli_list_next(ups->conn, query_num, query, &answer_num, @@ -211,7 +365,7 @@ static int nut_read_one(nut_ups_t *ups) { } } /* while (upscli_list_next) */ - return (0); + return 0; } /* int nut_read_one */ static int nut_read(void) { @@ -223,7 +377,7 @@ static int nut_read(void) { pthread_mutex_unlock(&read_lock); if (success != 0) - return (0); + return 0; for (nut_ups_t *ups = upslist_head; ups != NULL; ups = ups->next) if (nut_read_one(ups) == 0) @@ -233,7 +387,7 @@ static int nut_read(void) { read_busy = 0; pthread_mutex_unlock(&read_lock); - return ((success != 0) ? 0 : -1); + return (success != 0) ? 0 : -1; } /* int nut_read */ static int nut_shutdown(void) { @@ -246,8 +400,11 @@ static int nut_shutdown(void) { free_nut_ups_t(this); this = next; } +#if HAVE_UPSCLI_INIT + upscli_cleanup(); +#endif - return (0); + return 0; } /* int nut_shutdown */ void module_register(void) { @@ -255,5 +412,3 @@ void module_register(void) { plugin_register_read("nut", nut_read); plugin_register_shutdown("nut", nut_shutdown); } /* void module_register */ - -/* vim: set sw=2 ts=8 sts=2 tw=78 : */