X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fnut.c;h=5acbdde63946eecae6e751456a207057d77170b4;hb=fb0cc621d4357bbe4a9dc36c7f055f46257ce57c;hp=0d506f03d446b560c69c22771434a404a54b61a0;hpb=7fe1468b158ac6cc6399dc6c38c0c2dc50bba5c5;p=collectd.git diff --git a/src/nut.c b/src/nut.c index 0d506f03..5acbdde6 100644 --- a/src/nut.c +++ b/src/nut.c @@ -54,9 +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", "FORCESSL"}; +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) { @@ -112,11 +114,38 @@ static int nut_force_ssl(const char *value) { 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 */ @@ -139,14 +168,125 @@ 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; char **answer; unsigned int answer_num; int status; - int ssl_status; - int ssl_flags; /* (Re-)Connect if we have no connection */ if (ups->conn == NULL) { @@ -156,36 +296,9 @@ static int nut_read_one(nut_ups_t *ups) { return (-1); } - 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_read_one: 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 and VERIFICATION - 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."); - } - else if (ssl_status == 0){ - WARNING("nut plugin: Connection is unsecured (no SSL)."); - }else{ - ERROR("nut plugin: nut_read_one: upscli_ssl failed: %s", - upscli_strerror(ups->conn)); - sfree(ups->conn); - return (-1); - } /* if (ssl_status == 1 && verify_peer == 1) */ + status = nut_connect(ups); + if (status == -1) + return -1; } /* if (ups->conn == NULL) */ @@ -197,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); } @@ -284,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 */