aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2020-02-26 17:43:56 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2020-02-27 17:40:57 +0200
commit9b546466f4e0f34a63e5f49c752dffea3ef9a47a (patch)
treec22c12030250c22e76bf3c4c3cfcfb2a51b614c0
parent3b2d57c14f1ed207c79362b7136e3da4054ad817 (diff)
downloadping903-9b546466f4e0f34a63e5f49c752dffea3ef9a47a.tar.gz
ping903-9b546466f4e0f34a63e5f49c752dffea3ef9a47a.tar.bz2
ping903q: optionally supply credentials in the command line
New command line option -R supplies the authentication realm for ping903q. If given, the credentials for that realm will be looked up on startup and sent with each HTTP request. This allows the program to avoid sending an extra HTTP request. * src/ping903q.c (get_auth_creds): Split into two functions: get_auth_creds and get_realm_creds. (http_query): Don't attemt send lookup for authorization credentials. (main): New option -R (authentication realm). Look up credentials for that realm if given.
-rw-r--r--src/ping903q.c152
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) {

Return to:

Send suggestions and report system problems to the System administrator.