XRootD
Loading...
Searching...
No Matches
XrdHttpUtils.cc File Reference

Utility functions for XrdHTTP. More...

#include "XrdHttpUtils.hh"
#include <cstring>
#include <openssl/hmac.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include "sys/param.h"
#include <pthread.h>
#include <memory>
#include <vector>
#include <algorithm>
#include "XrdSec/XrdSecEntity.hh"
#include "XrdOuc/XrdOucString.hh"
+ Include dependency graph for XrdHttpUtils.cc:

Go to the source code of this file.

Functions

void calcHashes (char *hash, const char *fn, kXR_int16 request, XrdSecEntity *secent, time_t tim, const char *key)
 
static int char_to_int (int c)
 
int compareHash (const char *h1, const char *h2)
 
char * escapeXML (const char *str)
 
bool Fromhexdigest (const unsigned char *input, int length, unsigned char *out)
 
static void HMAC_CTX_free (HMAC_CTX *ctx)
 
static HMAC_CTX * HMAC_CTX_new ()
 
std::string httpStatusToString (int status)
 
std::string itos (long i)
 
int mapErrNoToHttp (int errNo)
 
int mapXrdErrToHttp (XErrorCode xrdError)
 
char * mystrchrnul (const char *s, int c)
 
int parseURL (char *url, char *host, int &port, char **path)
 
char * quote (const char *str)
 
void Tobase64 (const unsigned char *input, int length, char *out)
 
char * unquote (char *str)
 

Detailed Description

Utility functions for XrdHTTP.

Author
Fabrizio Furano
Date
April 2013

Definition in file XrdHttpUtils.cc.

Function Documentation

◆ calcHashes()

void calcHashes ( char * hash,
const char * fn,
kXR_int16 request,
XrdSecEntity * secent,
time_t tim,
const char * key )

Definition at line 219 of file XrdHttpUtils.cc.

230 {
231
232
233#if OPENSSL_VERSION_NUMBER >= 0x30000000L
234 EVP_MAC *mac;
235 EVP_MAC_CTX *ctx;
236 size_t len;
237#else
238 HMAC_CTX *ctx;
239 unsigned int len;
240#endif
241 unsigned char mdbuf[EVP_MAX_MD_SIZE];
242 char buf[64];
243 struct tm tms;
244
245
246 if (!hash) {
247 return;
248 }
249 hash[0] = '\0';
250
251 if (!key) {
252 return;
253 }
254
255 if (!fn || !secent) {
256 return;
257 }
258
259#if OPENSSL_VERSION_NUMBER >= 0x30000000L
260
261 if (!(mac = EVP_MAC_fetch(nullptr, "HMAC", nullptr))) {
262 return;
263 }
264
265 if (!(ctx = EVP_MAC_CTX_new(mac))) {
266 EVP_MAC_free(mac);
267 return;
268 }
269
270 OSSL_PARAM params[2] = {
271 OSSL_PARAM_construct_utf8_string("digest", (char*)"SHA256", 0),
272 OSSL_PARAM_construct_end()
273 };
274
275 if (!EVP_MAC_init(ctx, (const unsigned char *) key, strlen(key), params)) {
276 EVP_MAC_CTX_free(ctx);
277 EVP_MAC_free(mac);
278 return;
279 }
280
281 if (fn)
282 EVP_MAC_update(ctx, (const unsigned char *) fn,
283 strlen(fn) + 1);
284
285 EVP_MAC_update(ctx, (const unsigned char *) &request,
286 sizeof (request));
287
288 if (secent->name)
289 EVP_MAC_update(ctx, (const unsigned char *) secent->name,
290 strlen(secent->name) + 1);
291
292 if (secent->vorg)
293 EVP_MAC_update(ctx, (const unsigned char *) secent->vorg,
294 strlen(secent->vorg) + 1);
295
296 if (secent->host)
297 EVP_MAC_update(ctx, (const unsigned char *) secent->host,
298 strlen(secent->host) + 1);
299
300 if (secent->moninfo)
301 EVP_MAC_update(ctx, (const unsigned char *) secent->moninfo,
302 strlen(secent->moninfo) + 1);
303
304 localtime_r(&tim, &tms);
305 strftime(buf, sizeof (buf), "%s", &tms);
306 EVP_MAC_update(ctx, (const unsigned char *) buf,
307 strlen(buf) + 1);
308
309 EVP_MAC_final(ctx, mdbuf, &len, EVP_MAX_MD_SIZE);
310
311 EVP_MAC_CTX_free(ctx);
312 EVP_MAC_free(mac);
313
314#else
315
316 ctx = HMAC_CTX_new();
317
318 if (!ctx) {
319 return;
320 }
321
322
323
324 HMAC_Init_ex(ctx, (const void *) key, strlen(key), EVP_sha256(), 0);
325
326
327 if (fn)
328 HMAC_Update(ctx, (const unsigned char *) fn,
329 strlen(fn) + 1);
330
331 HMAC_Update(ctx, (const unsigned char *) &request,
332 sizeof (request));
333
334 if (secent->name)
335 HMAC_Update(ctx, (const unsigned char *) secent->name,
336 strlen(secent->name) + 1);
337
338 if (secent->vorg)
339 HMAC_Update(ctx, (const unsigned char *) secent->vorg,
340 strlen(secent->vorg) + 1);
341
342 if (secent->host)
343 HMAC_Update(ctx, (const unsigned char *) secent->host,
344 strlen(secent->host) + 1);
345
346 if (secent->moninfo)
347 HMAC_Update(ctx, (const unsigned char *) secent->moninfo,
348 strlen(secent->moninfo) + 1);
349
350 localtime_r(&tim, &tms);
351 strftime(buf, sizeof (buf), "%s", &tms);
352 HMAC_Update(ctx, (const unsigned char *) buf,
353 strlen(buf) + 1);
354
355 HMAC_Final(ctx, mdbuf, &len);
356
357 HMAC_CTX_free(ctx);
358
359#endif
360
361 Tobase64(mdbuf, len / 2, hash);
362}
void Tobase64(const unsigned char *input, int length, char *out)
static HMAC_CTX * HMAC_CTX_new()
static void HMAC_CTX_free(HMAC_CTX *ctx)
char * vorg
Entity's virtual organization(s)
char * name
Entity's name.
char * moninfo
Information for monitoring.
char * host
Entity's host name dnr dependent.

References HMAC_CTX_free(), HMAC_CTX_new(), XrdSecEntity::host, XrdSecEntity::moninfo, XrdSecEntity::name, Tobase64(), and XrdSecEntity::vorg.

Referenced by XrdHttpProtocol::Process(), and XrdHttpReq::Redir().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ char_to_int()

static int char_to_int ( int c)
static

Definition at line 153 of file XrdHttpUtils.cc.

154{
155 if (isdigit(c)) {
156 return c - '0';
157 } else {
158 c = tolower(c);
159 if (c >= 'a' && c <= 'f') {
160 return c - 'a' + 10;
161 }
162 return -1;
163 }
164}

Referenced by Fromhexdigest().

+ Here is the caller graph for this function:

◆ compareHash()

int compareHash ( const char * h1,
const char * h2 )

Definition at line 364 of file XrdHttpUtils.cc.

366 {
367
368 if (h1 == h2) return 0;
369
370 if (!h1 || !h2)
371 return 1;
372
373 return strcmp(h1, h2);
374
375}

Referenced by XrdHttpProtocol::Process().

+ Here is the caller graph for this function:

◆ escapeXML()

char * escapeXML ( const char * str)

Definition at line 470 of file XrdHttpUtils.cc.

470 {
471 int l = strlen(str);
472 char *r = (char *) malloc(l*6 + 1);
473 r[0] = '\0';
474 int i, j = 0;
475
476 for (i = 0; i < l; i++) {
477 char c = str[i];
478
479 switch (c) {
480 case '"':
481 strcpy(r + j, "&quot;");
482 j += 6;
483 break;
484 case '&':
485 strcpy(r + j, "&amp;");
486 j += 5;
487 break;
488 case '<':
489 strcpy(r + j, "&lt;");
490 j += 4;
491 break;
492 case '>':
493 strcpy(r + j, "&gt;");
494 j += 4;
495 break;
496 case '\'':
497 strcpy(r + j, "&apos;");
498 j += 6;
499 break;
500
501 default:
502 r[j++] = c;
503 }
504 }
505
506 r[j] = '\0';
507
508 return r;
509}

Referenced by XrdHttpReq::Error().

+ Here is the caller graph for this function:

◆ Fromhexdigest()

bool Fromhexdigest ( const unsigned char * input,
int length,
unsigned char * out )

Definition at line 169 of file XrdHttpUtils.cc.

169 {
170 for (int idx=0; idx < length; idx += 2) {
171 int upper = char_to_int(input[idx]);
172 int lower = char_to_int(input[idx+1]);
173 if ((upper < 0) || (lower < 0)) {
174 return false;
175 }
176 out[idx/2] = (upper << 4) + lower;
177 }
178 return true;
179}
static int char_to_int(int c)

References char_to_int().

+ Here is the call graph for this function:

◆ HMAC_CTX_free()

static void HMAC_CTX_free ( HMAC_CTX * ctx)
static

Definition at line 65 of file XrdHttpUtils.cc.

65 {
66 if (ctx) {
67 HMAC_CTX_cleanup(ctx);
68 OPENSSL_free(ctx);
69 }
70}

Referenced by calcHashes().

+ Here is the caller graph for this function:

◆ HMAC_CTX_new()

static HMAC_CTX * HMAC_CTX_new ( )
static

Definition at line 59 of file XrdHttpUtils.cc.

59 {
60 HMAC_CTX *ctx = (HMAC_CTX *)OPENSSL_malloc(sizeof(HMAC_CTX));
61 if (ctx) HMAC_CTX_init(ctx);
62 return ctx;
63}

Referenced by calcHashes().

+ Here is the caller graph for this function:

◆ httpStatusToString()

std::string httpStatusToString ( int status)

Definition at line 591 of file XrdHttpUtils.cc.

591 {
592 switch (status) {
593 // 1xx Informational
594 case 100: return "Continue";
595 case 101: return "Switching Protocols";
596 case 102: return "Processing";
597 case 103: return "Early Hints";
598
599 // 2xx Success
600 case 200: return "OK";
601 case 201: return "Created";
602 case 202: return "Accepted";
603 case 203: return "Non-Authoritative Information";
604 case 204: return "No Content";
605 case 205: return "Reset Content";
606 case 206: return "Partial Content";
607 case 207: return "Multi-Status";
608 case 208: return "Already Reported";
609 case 226: return "IM Used";
610
611 // 3xx Redirection
612 case 300: return "Multiple Choices";
613 case 301: return "Moved Permanently";
614 case 302: return "Found";
615 case 303: return "See Other";
616 case 304: return "Not Modified";
617 case 305: return "Use Proxy";
618 case 307: return "Temporary Redirect";
619 case 308: return "Permanent Redirect";
620
621 // 4xx Client Errors
622 case 400: return "Bad Request";
623 case 401: return "Unauthorized";
624 case 402: return "Payment Required";
625 case 403: return "Forbidden";
626 case 404: return "Not Found";
627 case 405: return "Method Not Allowed";
628 case 406: return "Not Acceptable";
629 case 407: return "Proxy Authentication Required";
630 case 408: return "Request Timeout";
631 case 409: return "Conflict";
632 case 410: return "Gone";
633 case 411: return "Length Required";
634 case 412: return "Precondition Failed";
635 case 413: return "Payload Too Large";
636 case 414: return "URI Too Long";
637 case 415: return "Unsupported Media Type";
638 case 416: return "Range Not Satisfiable";
639 case 417: return "Expectation Failed";
640 case 418: return "I'm a teapot";
641 case 421: return "Misdirected Request";
642 case 422: return "Unprocessable Entity";
643 case 423: return "Locked";
644 case 424: return "Failed Dependency";
645 case 425: return "Too Early";
646 case 426: return "Upgrade Required";
647 case 428: return "Precondition Required";
648 case 429: return "Too Many Requests";
649 case 431: return "Request Header Fields Too Large";
650 case 451: return "Unavailable For Legal Reasons";
651
652 // 5xx Server Errors
653 case 500: return "Internal Server Error";
654 case 501: return "Not Implemented";
655 case 502: return "Bad Gateway";
656 case 503: return "Service Unavailable";
657 case 504: return "Gateway Timeout";
658 case 505: return "HTTP Version Not Supported";
659 case 506: return "Variant Also Negotiates";
660 case 507: return "Insufficient Storage";
661 case 508: return "Loop Detected";
662 case 510: return "Not Extended";
663 case 511: return "Network Authentication Required";
664
665 default:
666 switch (status) {
667 case 100 ... 199: return "Informational";
668 case 200 ... 299: return "Success";
669 case 300 ... 399: return "Redirection";
670 case 400 ... 499: return "Client Error";
671 case 500 ... 599: return "Server Error";
672 default: return "Unknown";
673 }
674 }
675}

◆ itos()

std::string itos ( long i)

Definition at line 183 of file XrdHttpUtils.cc.

183 {
184 char buf[128];
185 sprintf(buf, "%ld", i);
186
187 return buf;
188}

◆ mapErrNoToHttp()

int mapErrNoToHttp ( int errNo)

Definition at line 518 of file XrdHttpUtils.cc.

518 {
519
520 switch (errNo) {
521
522 case EACCES:
523 case EROFS:
524 case EPERM:
525 return HTTP_FORBIDDEN;
526
527 case EAUTH:
528 return HTTP_UNAUTHORIZED;
529
530 case ENOENT:
531 return HTTP_NOT_FOUND;
532
533 case EEXIST:
534 case EISDIR:
535 case ENOTDIR:
536 case ENOTEMPTY:
537 return HTTP_CONFLICT;
538
539 case EXDEV:
541
542 case ENAMETOOLONG:
543 return HTTP_URI_TOO_LONG;
544
545 case ELOOP:
546 return HTTP_LOOP_DETECTED;
547
548 case ENOSPC:
549 case EDQUOT:
551
552 case EFBIG:
554
555 case EINVAL:
556 case EBADF:
557 case EFAULT:
558 case ENXIO:
559 case ESPIPE:
560 case EOVERFLOW:
561 return HTTP_BAD_REQUEST;
562
563 case ENOTSUP: // EOPNOTSUPP
565
566 case EBUSY:
567 case EAGAIN:
568 case EINTR:
569 case ENOMEM:
570 case EMFILE:
571 case ENFILE:
572 case ETXTBSY:
574
575 case ETIMEDOUT:
577
578 case ECONNREFUSED:
579 case ECONNRESET:
580 case ENETDOWN:
581 case ENETUNREACH:
582 case EHOSTUNREACH:
583 case EPIPE:
584 return HTTP_BAD_GATEWAY;
585
586 default:
588 }
589}
#define EAUTH
@ HTTP_INSUFFICIENT_STORAGE
@ HTTP_BAD_REQUEST
@ HTTP_LOOP_DETECTED
@ HTTP_SERVICE_UNAVAILABLE
@ HTTP_URI_TOO_LONG
@ HTTP_UNAUTHORIZED
@ HTTP_NOT_FOUND
@ HTTP_FORBIDDEN
@ HTTP_BAD_GATEWAY
@ HTTP_GATEWAY_TIMEOUT
@ HTTP_INTERNAL_SERVER_ERROR
@ HTTP_PAYLOAD_TOO_LARGE
@ HTTP_NOT_IMPLEMENTED
@ HTTP_UNPROCESSABLE_ENTITY
@ HTTP_CONFLICT

References EAUTH, HTTP_BAD_GATEWAY, HTTP_BAD_REQUEST, HTTP_CONFLICT, HTTP_FORBIDDEN, HTTP_GATEWAY_TIMEOUT, HTTP_INSUFFICIENT_STORAGE, HTTP_INTERNAL_SERVER_ERROR, HTTP_LOOP_DETECTED, HTTP_NOT_FOUND, HTTP_NOT_IMPLEMENTED, HTTP_PAYLOAD_TOO_LARGE, HTTP_SERVICE_UNAVAILABLE, HTTP_UNAUTHORIZED, HTTP_UNPROCESSABLE_ENTITY, and HTTP_URI_TOO_LONG.

Referenced by mapXrdErrToHttp().

+ Here is the caller graph for this function:

◆ mapXrdErrToHttp()

int mapXrdErrToHttp ( XErrorCode xrdError)

Definition at line 511 of file XrdHttpUtils.cc.

511 {
512
513 int errNo = XProtocol::toErrno(xrdError);
514 return mapErrNoToHttp(errNo);
515
516}
int mapErrNoToHttp(int errNo)
static int toErrno(int xerr)

References mapErrNoToHttp(), and XProtocol::toErrno().

+ Here is the call graph for this function:

◆ mystrchrnul()

char * mystrchrnul ( const char * s,
int c )

Definition at line 193 of file XrdHttpUtils.cc.

193 {
194 char *ptr = strchr((char *)s, c);
195
196 if (!ptr)
197 return strchr((char *)s, '\0');
198
199 return ptr;
200}

◆ parseURL()

int parseURL ( char * url,
char * host,
int & port,
char ** path )

Definition at line 77 of file XrdHttpUtils.cc.

77 {
78 // http://x.y.z.w:p/path
79
80 *path = 0;
81
82 // look for the second slash
83 char *p = strstr(url, "//");
84 if (!p) return -1;
85
86
87 p += 2;
88
89 // look for the end of the host:port
90 char *p2 = strchr(p, '/');
91 if (!p2) return -1;
92
93 *path = p2;
94
95 char buf[256];
96 int l = std::min((int)(p2 - p), (int)sizeof (buf) - 1);
97 strncpy(buf, p, l);
98 buf[l] = '\0';
99
100 // Now look for :
101 p = strchr(buf, ':');
102 if (p) {
103 int l = std::min((int)(p - buf), (int)sizeof (buf) - 1);
104 strncpy(host, buf, l);
105 host[l] = '\0';
106
107 port = atoi(p + 1);
108 } else {
109 port = 0;
110
111
112 strcpy(host, buf);
113 }
114
115 return 0;
116}

◆ quote()

char * quote ( const char * str)

Definition at line 411 of file XrdHttpUtils.cc.

411 {
412 int l = strlen(str);
413 char *r = (char *) malloc(l*3 + 1);
414 r[0] = '\0';
415 int i, j = 0;
416
417 for (i = 0; i < l; i++) {
418 char c = str[i];
419
420 switch (c) {
421 case ' ':
422 strcpy(r + j, "%20");
423 j += 3;
424 break;
425 case '[':
426 strcpy(r + j, "%5B");
427 j += 3;
428 break;
429 case ']':
430 strcpy(r + j, "%5D");
431 j += 3;
432 break;
433 case ':':
434 strcpy(r + j, "%3A");
435 j += 3;
436 break;
437 // case '/':
438 // strcpy(r + j, "%2F");
439 // j += 3;
440 // break;
441 case '#':
442 strcpy(r + j, "%23");
443 j += 3;
444 break;
445 case '\n':
446 strcpy(r + j, "%0A");
447 j += 3;
448 break;
449 case '\r':
450 strcpy(r + j, "%0D");
451 j += 3;
452 break;
453 case '=':
454 strcpy(r + j, "%3D");
455 j += 3;
456 break;
457 default:
458 r[j++] = c;
459 }
460 }
461
462 r[j] = '\0';
463
464 return r;
465}

Referenced by encode_raw().

+ Here is the caller graph for this function:

◆ Tobase64()

void Tobase64 ( const unsigned char * input,
int length,
char * out )

Definition at line 121 of file XrdHttpUtils.cc.

121 {
122 BIO *bmem, *b64;
123 BUF_MEM *bptr;
124
125 if (!out) return;
126
127 out[0] = '\0';
128
129 b64 = BIO_new(BIO_f_base64());
130 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
131 bmem = BIO_new(BIO_s_mem());
132 BIO_push(b64, bmem);
133 BIO_write(b64, input, length);
134
135 if (BIO_flush(b64) <= 0) {
136 BIO_free_all(b64);
137 return;
138 }
139
140 BIO_get_mem_ptr(b64, &bptr);
141
142
143 memcpy(out, bptr->data, bptr->length);
144 out[bptr->length] = '\0';
145
146 BIO_free_all(b64);
147
148 return;
149}
void BIO_set_flags(BIO *bio, int flags)

References BIO_set_flags().

Referenced by calcHashes().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ unquote()

char * unquote ( char * str)

Definition at line 379 of file XrdHttpUtils.cc.

379 {
380 int l = strlen(str);
381 char *r = (char *) malloc(l + 1);
382 r[0] = '\0';
383 int i, j = 0;
384
385 for (i = 0; i < l; i++) {
386 if (str[i] == '%') {
387 if (i + 3 > l) {
388 r[j] = '\0';
389 return r;
390 }
391 char savec = str[i + 3];
392 str[i + 3] = '\0';
393
394 r[j] = strtol(str + i + 1, 0, 16);
395 str[i + 3] = savec;
396
397 i += 2;
398 } else r[j] = str[i];
399
400 j++;
401 }
402
403 r[j] = '\0';
404
405 return r;
406
407}

Referenced by decode_raw().

+ Here is the caller graph for this function: