diff options
-rw-r--r-- | src/ping903q.c | 152 |
1 files changed, 100 insertions, 52 deletions
diff --git a/src/ping903q.c b/src/ping903q.c index 85388f8..a9024c7 100644 --- a/src/ping903q.c +++ b/src/ping903q.c @@ -385,9 +385,13 @@ http_query_primitive(char const *meth, char const *url, char **hdr) static char *std_headers[] = { "Accept: application/json", "User-Agent: ping903q (" PACKAGE_STRING ")", - NULL + NULL, + NULL, }; +/* Place where to insert the Authorization header to std_headers */ +#define AUTH_HDR_IDX 2 + #define BASICPREF "Basic realm=\"" #define BASICLEN (sizeof(BASICPREF)-1) @@ -478,10 +482,13 @@ machinecmp(char const *pat) return strcmp(pat, service); } +#define HTTP_AUTHORIZATION "Authorization: Basic " +#define HTTP_AUTHORIZATION_LEN (sizeof(HTTP_AUTHORIZATION)-1) + static int -get_auth_creds(char const *auth, char **retval) +get_realm_creds(char const *realm, char **retval) { - char *realm, *p; + char *p; size_t len; char const *cfname; FILE *fp; @@ -489,32 +496,11 @@ get_auth_creds(char const *auth, char **retval) int ln = 0; int skip_to_eol = 0; int ret; - int i; - if (!auth || strncmp(auth, BASICPREF, BASICLEN)) - return -1; - auth += BASICLEN; - len = strlen(auth); - if (len == 0 || auth[len-1] != '"') - return -1; - len--; - if (auth[len-1] == '\\') - return -1; - realm = emalloc(len + 1); - memcpy(realm, auth, len); - for (i = 0; i < len; ) { - if (*auth == '\\') - auth++; - realm[i++] = *auth++; - } - realm[i] = 0; - cfname = get_cred_file_name(); fp = fopen(cfname, "r"); - if (!fp) { - free(realm); + if (!fp) return -1; - } ret = -1; while (fgets(buf, sizeof(buf), fp)) { @@ -577,11 +563,33 @@ get_auth_creds(char const *auth, char **retval) && (strcmp(av[1], "*") == 0 || strcmp(av[1], realm) == 0)) { len = strlen(av[2]) + strlen(av[3]) + 2; - char *p = emalloc(len); - strcpy(p, av[2]); - strcat(p, ":"); - strcat(p, av[3]); - *retval = p; + char *plaintext; + char *b64; + size_t b64_len; + char *hdr; + + /* Create plaintext auth string */ + plaintext = emalloc(len); + strcpy(plaintext, av[2]); + strcat(plaintext, ":"); + strcat(plaintext, av[3]); + + /* Encode it to base64 */ + if (base64_encode(plaintext, len, &b64, &b64_len)) + emalloc_die(); + + free(plaintext); + + /* Create Authorization header */ + hdr = emalloc(HTTP_AUTHORIZATION_LEN + + b64_len + + 1); + strcpy(hdr, HTTP_AUTHORIZATION); + strcat(hdr, b64); + free(b64); + + /* Return it */ + *retval = hdr; ret = 0; argcv_free(ac, av); break; @@ -591,12 +599,52 @@ get_auth_creds(char const *auth, char **retval) } err: fclose(fp); - free(realm); return ret; } -#define HTTP_AUTHORIZATION "Authorization: Basic " -#define HTTP_AUTHORIZATION_LEN (sizeof(HTTP_AUTHORIZATION)-1) +static int +get_auth_creds(char const *auth, char **retval) +{ + char *realm; + size_t len; + int rc; + int i; + + if (!auth || strncmp(auth, BASICPREF, BASICLEN)) + return -1; + auth += BASICLEN; + len = strlen(auth); + if (len == 0 || auth[len-1] != '"') + return -1; + len--; + if (auth[len-1] == '\\') + return -1; + realm = emalloc(len + 1); + memcpy(realm, auth, len); + for (i = 0; i < len; ) { + if (*auth == '\\') + auth++; + realm[i++] = *auth++; + } + realm[i] = 0; + + rc = get_realm_creds(realm, retval); + free(realm); + return rc; +} + +static int +has_authorization(char **hdr) +{ + size_t i; + if (!hdr) + return 0; + for (i = 0; hdr[i]; i++) + if (strncmp(hdr[i], HTTP_AUTHORIZATION, + HTTP_AUTHORIZATION_LEN) == 0) + return 1; + return 0; +} static void http_query(char const *meth, char const *url, char **hdr, @@ -605,17 +653,14 @@ http_query(char const *meth, char const *url, char **hdr, http_query_primitive(meth, url, hdr); http_recv(resp); if (resp->code != 200) { - if (resp->code == 401) { + if (resp->code == 401 && !has_authorization(hdr)) { char *creds; char const *auth = http_resp_get_header(resp, "WWW-Authenticate"); if (get_auth_creds(auth, &creds) == 0) { - char *b64creds; - size_t b64creds_len; char **new_hdr; size_t i, nhdr; - char *auth_hdr; for (nhdr = 0; hdr[nhdr]; nhdr++) ; @@ -623,26 +668,14 @@ http_query(char const *meth, char const *url, char **hdr, sizeof(new_hdr[0])); for (i = 0; i < nhdr; i++) new_hdr[i] = hdr[i]; - - if (base64_encode(creds, strlen(creds), - &b64creds, &b64creds_len)) - emalloc_die(); - free(creds); - - auth_hdr = emalloc(HTTP_AUTHORIZATION_LEN - + b64creds_len - + 1); - strcpy(auth_hdr, HTTP_AUTHORIZATION); - strcat(auth_hdr, b64creds); - free(b64creds); - new_hdr[i] = auth_hdr; + new_hdr[i] = creds; new_hdr[i+1] = NULL; http_query_primitive(meth, url, new_hdr); http_recv(resp); free(new_hdr); - free(auth_hdr); + free(creds); } } } @@ -997,6 +1030,7 @@ usage(void) printf("Options:\n\n"); printf(" -f FILE read configuration from FILE\n"); printf(" -h print this help test\n"); + printf(" -R REALM use credentials for this authentication realm\n"); printf(" -r resolve HOST to IP address\n"); printf(" -V print program version and exit\n"); printf(" -v additional verbosity\n"); @@ -1045,6 +1079,7 @@ main(int argc, char **argv) char const *host = NULL; char *c_opt = NULL; char *w_opt = NULL; + char *realm = NULL; struct nagios_check_data chkdata; set_progname(argv[0]); @@ -1059,7 +1094,7 @@ main(int argc, char **argv) exit(0); } } - while ((c = getopt(argc, argv, "c:f:H:hmp:rVvw:")) != EOF) { + while ((c = getopt(argc, argv, "c:f:H:hmp:R:rVvw:")) != EOF) { switch (c) { case 'c': c_opt = optarg; @@ -1081,6 +1116,9 @@ main(int argc, char **argv) case 'p': nagios_prefix_format = optarg; break; + case 'R': + realm = optarg; + break; case 'r': resolve_ip = 1; break; @@ -1132,6 +1170,16 @@ main(int argc, char **argv) http_connect(nodename, service); free(p); + if (realm) { + char *auth_hdr; + if (get_realm_creds(realm, &auth_hdr) == 0) { + std_headers[AUTH_HDR_IDX] = auth_hdr; + } else + error("can't find credentials for realm %s at %s:%s", + realm, nodename, service); + } + + switch (mode) { case MODE_DEFAULT: switch (argc) { |