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 <pthread.h>
#include <memory>
#include <vector>
#include <algorithm>
#include "XProtocol/XPtypes.hh"
#include "XrdSec/XrdSecEntity.hh"
#include "sys/param.h"
#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)
 
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 220 of file XrdHttpUtils.cc.

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

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

Referenced by Fromhexdigest().

+ Here is the caller graph for this function:

◆ compareHash()

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

Definition at line 356 of file XrdHttpUtils.cc.

358  {
359 
360  if (h1 == h2) return 0;
361 
362  if (!h1 || !h2)
363  return 1;
364 
365  return strcmp(h1, h2);
366 
367 }

Referenced by XrdHttpProtocol::Process().

+ Here is the caller graph for this function:

◆ escapeXML()

char* escapeXML ( const char *  str)

Definition at line 459 of file XrdHttpUtils.cc.

459  {
460  int l = strlen(str);
461  char *r = (char *) malloc(l*6 + 1);
462  r[0] = '\0';
463  int i, j = 0;
464 
465  for (i = 0; i < l; i++) {
466  char c = str[i];
467 
468  switch (c) {
469  case '"':
470  strcpy(r + j, "&quot;");
471  j += 6;
472  break;
473  case '&':
474  strcpy(r + j, "&amp;");
475  j += 5;
476  break;
477  case '<':
478  strcpy(r + j, "&lt;");
479  j += 4;
480  break;
481  case '>':
482  strcpy(r + j, "&gt;");
483  j += 4;
484  break;
485  case '\'':
486  strcpy(r + j, "&apos;");
487  j += 6;
488  break;
489 
490  default:
491  r[j++] = c;
492  }
493  }
494 
495  r[j] = '\0';
496 
497  return r;
498 }

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 170 of file XrdHttpUtils.cc.

170  {
171  for (int idx=0; idx < length; idx += 2) {
172  int upper = char_to_int(input[idx]);
173  int lower = char_to_int(input[idx+1]);
174  if ((upper < 0) || (lower < 0)) {
175  return false;
176  }
177  out[idx/2] = (upper << 4) + lower;
178  }
179  return true;
180 }
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 66 of file XrdHttpUtils.cc.

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

Referenced by calcHashes().

+ Here is the caller graph for this function:

◆ HMAC_CTX_new()

static HMAC_CTX* HMAC_CTX_new ( )
static

Definition at line 60 of file XrdHttpUtils.cc.

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

Referenced by calcHashes().

+ Here is the caller graph for this function:

◆ httpStatusToString()

std::string httpStatusToString ( int  status)

Definition at line 573 of file XrdHttpUtils.cc.

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

◆ itos()

std::string itos ( long  i)

Definition at line 184 of file XrdHttpUtils.cc.

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

◆ mapErrNoToHttp()

int mapErrNoToHttp ( int  errNo)

Definition at line 500 of file XrdHttpUtils.cc.

500  {
501 
502  switch (errNo) {
503 
504  case EACCES:
505  case EROFS:
506  return HTTP_FORBIDDEN;
507 
508  case EPERM:
509  return HTTP_UNAUTHORIZED;
510 
511  case ENOENT:
512  return HTTP_NOT_FOUND;
513 
514  case EEXIST:
515  case ENOTEMPTY:
516  return HTTP_CONFLICT;
517 
518  case ENOTDIR:
519  case EISDIR:
520  case EXDEV:
522 
523  case ENAMETOOLONG:
524  return HTTP_URI_TOO_LONG;
525 
526  case ELOOP:
527  return HTTP_LOOP_DETECTED;
528 
529  case ENOSPC:
530  case EDQUOT:
532 
533  case EFBIG:
534  return HTTP_PAYLOAD_TOO_LARGE;
535 
536  case EINVAL:
537  case EBADF:
538  case EFAULT:
539  case ENXIO:
540  case ESPIPE:
541  case ENODEV:
542  case EOVERFLOW:
543  return HTTP_BAD_REQUEST;
544 
545  case ENOTSUP: // EOPNOTSUPP
546  return HTTP_NOT_IMPLEMENTED;
547 
548  case EBUSY:
549  case EAGAIN:
550  case EINTR:
551  case ENOMEM:
552  case EMFILE:
553  case ENFILE:
554  case ETXTBSY:
556 
557  case ETIMEDOUT:
558  return HTTP_GATEWAY_TIMEOUT;
559 
560  case ECONNREFUSED:
561  case ECONNRESET:
562  case ENETDOWN:
563  case ENETUNREACH:
564  case EHOSTUNREACH:
565  case EPIPE:
566  return HTTP_BAD_GATEWAY;
567 
568  default:
570  }
571 }
@ HTTP_INSUFFICIENT_STORAGE
@ HTTP_BAD_REQUEST
Definition: XrdHttpUtils.hh:80
@ HTTP_LOOP_DETECTED
@ HTTP_SERVICE_UNAVAILABLE
@ HTTP_URI_TOO_LONG
Definition: XrdHttpUtils.hh:94
@ HTTP_UNAUTHORIZED
Definition: XrdHttpUtils.hh:81
@ HTTP_NOT_FOUND
Definition: XrdHttpUtils.hh:84
@ HTTP_FORBIDDEN
Definition: XrdHttpUtils.hh:83
@ HTTP_BAD_GATEWAY
@ HTTP_GATEWAY_TIMEOUT
@ HTTP_INTERNAL_SERVER_ERROR
@ HTTP_PAYLOAD_TOO_LARGE
Definition: XrdHttpUtils.hh:93
@ HTTP_NOT_IMPLEMENTED
@ HTTP_UNPROCESSABLE_ENTITY
@ HTTP_CONFLICT
Definition: XrdHttpUtils.hh:89

References 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.

◆ mystrchrnul()

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

Definition at line 194 of file XrdHttpUtils.cc.

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

◆ parseURL()

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

Definition at line 78 of file XrdHttpUtils.cc.

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

Referenced by XrdHttpReq::ProcessHTTPReq().

+ Here is the caller graph for this function:

◆ quote()

char* quote ( const char *  str)

Definition at line 400 of file XrdHttpUtils.cc.

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

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 122 of file XrdHttpUtils.cc.

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

371  {
372  int l = strlen(str);
373  char *r = (char *) malloc(l + 1);
374  r[0] = '\0';
375  int i, j = 0;
376 
377  for (i = 0; i < l; i++) {
378 
379  if (str[i] == '%') {
380  char savec = str[i + 3];
381  str[i + 3] = '\0';
382 
383  r[j] = strtol(str + i + 1, 0, 16);
384  str[i + 3] = savec;
385 
386  i += 2;
387  } else r[j] = str[i];
388 
389  j++;
390  }
391 
392  r[j] = '\0';
393 
394  return r;
395 
396 }

Referenced by decode_raw().

+ Here is the caller graph for this function: