X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fnut.c;h=5acbdde63946eecae6e751456a207057d77170b4;hb=d3e97e2e0c710c1bbe0cac873bd1c5df004bc740;hp=d40e09510c1d7598dadc330ff53c4689576d0885;hpb=eec0cd9ca51c5c132ed09fc4699c02f3bd12d748;p=collectd.git diff --git a/src/nut.c b/src/nut.c index d40e0951..5acbdde6 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) { @@ -98,9 +101,51 @@ static int nut_add_ups(const char *name) { 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)); + 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); } /* int nut_config */ @@ -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) { +#ifdef WITH_UPSCLIENT_27 + 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 /* #ifdef WITH_UPSCLIENT_27 */ + 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; @@ -138,17 +296,10 @@ static int nut_read_one(nut_ups_t *ups) { 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,6 +310,9 @@ static int nut_read_one(nut_ups_t *ups) { ups->upsname, upscli_strerror(ups->conn)); upscli_disconnect(ups->conn); sfree(ups->conn); +#ifdef WITH_UPSCLIENT_27 + upscli_cleanup(); +#endif return (-1); } @@ -246,6 +400,9 @@ static int nut_shutdown(void) { free_nut_ups_t(this); this = next; } +#ifdef WITH_UPSCLIENT_27 + upscli_cleanup(); +#endif return (0); } /* int nut_shutdown */ @@ -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 : */