XRootD
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 void HMAC_CTX_free(HMAC_CTX *ctx)
Definition: XrdHttpUtils.cc:65
static HMAC_CTX * HMAC_CTX_new()
Definition: XrdHttpUtils.cc:59
char * vorg
Entity's virtual organization(s)
Definition: XrdSecEntity.hh:71
char * name
Entity's name.
Definition: XrdSecEntity.hh:69
char * moninfo
Information for monitoring.
Definition: XrdSecEntity.hh:76
char * host
Entity's host name dnr dependent.
Definition: XrdSecEntity.hh:70

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:
553  return HTTP_PAYLOAD_TOO_LARGE;
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
564  return HTTP_NOT_IMPLEMENTED;
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:
576  return HTTP_GATEWAY_TIMEOUT;
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
Definition: XProtocol.hh:1351
@ HTTP_INSUFFICIENT_STORAGE
@ HTTP_BAD_REQUEST
Definition: XrdHttpUtils.hh:81
@ HTTP_LOOP_DETECTED
@ HTTP_SERVICE_UNAVAILABLE
@ HTTP_URI_TOO_LONG
Definition: XrdHttpUtils.hh:95
@ HTTP_UNAUTHORIZED
Definition: XrdHttpUtils.hh:82
@ HTTP_NOT_FOUND
Definition: XrdHttpUtils.hh:85
@ HTTP_FORBIDDEN
Definition: XrdHttpUtils.hh:84
@ HTTP_BAD_GATEWAY
@ HTTP_GATEWAY_TIMEOUT
@ HTTP_INTERNAL_SERVER_ERROR
@ HTTP_PAYLOAD_TOO_LARGE
Definition: XrdHttpUtils.hh:94
@ HTTP_NOT_IMPLEMENTED
@ HTTP_UNPROCESSABLE_ENTITY
@ HTTP_CONFLICT
Definition: XrdHttpUtils.hh:90

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)
Definition: XProtocol.hh:1411

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: