httpauth.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /*
  2. * HTTP authentication
  3. * Copyright (c) 2010 Martin Storsjo
  4. *
  5. * This file is part of FFmpeg.
  6. *
  7. * FFmpeg is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * FFmpeg is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with FFmpeg; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. #include "httpauth.h"
  22. #include "libavutil/base64.h"
  23. #include "libavutil/avstring.h"
  24. #include "avformat.h"
  25. #include <ctype.h>
  26. static void parse_key_value(const char *params,
  27. void (*callback_get_buf)(HTTPAuthState *state,
  28. const char *key, int key_len,
  29. char **dest, int *dest_len), HTTPAuthState *state)
  30. {
  31. const char *ptr = params;
  32. /* Parse key=value pairs. */
  33. for (;;) {
  34. const char *key;
  35. char *dest = NULL, *dest_end;
  36. int key_len, dest_len = 0;
  37. /* Skip whitespace and potential commas. */
  38. while (*ptr && (isspace(*ptr) || *ptr == ','))
  39. ptr++;
  40. if (!*ptr)
  41. break;
  42. key = ptr;
  43. if (!(ptr = strchr(key, '=')))
  44. break;
  45. ptr++;
  46. key_len = ptr - key;
  47. callback_get_buf(state, key, key_len, &dest, &dest_len);
  48. dest_end = dest + dest_len - 1;
  49. if (*ptr == '\"') {
  50. ptr++;
  51. while (*ptr && *ptr != '\"') {
  52. if (*ptr == '\\') {
  53. if (!ptr[1])
  54. break;
  55. if (dest && dest < dest_end)
  56. *dest++ = ptr[1];
  57. ptr += 2;
  58. } else {
  59. if (dest && dest < dest_end)
  60. *dest++ = *ptr;
  61. ptr++;
  62. }
  63. }
  64. if (*ptr == '\"')
  65. ptr++;
  66. } else {
  67. for (; *ptr && !(isspace(*ptr) || *ptr == ','); ptr++)
  68. if (dest && dest < dest_end)
  69. *dest++ = *ptr;
  70. }
  71. if (dest)
  72. *dest = 0;
  73. }
  74. }
  75. static void handle_basic_params(HTTPAuthState *state, const char *key,
  76. int key_len, char **dest, int *dest_len)
  77. {
  78. if (!strncmp(key, "realm=", key_len)) {
  79. *dest = state->realm;
  80. *dest_len = sizeof(state->realm);
  81. }
  82. }
  83. void ff_http_auth_handle_header(HTTPAuthState *state, const char *key,
  84. const char *value)
  85. {
  86. if (!state)
  87. return;
  88. if (!strcmp(key, "WWW-Authenticate")) {
  89. const char *p;
  90. if (av_stristart(value, "Basic ", &p) &&
  91. state->auth_type <= HTTP_AUTH_BASIC) {
  92. state->auth_type = HTTP_AUTH_BASIC;
  93. state->realm[0] = 0;
  94. parse_key_value(p, handle_basic_params, state);
  95. }
  96. }
  97. }
  98. char *ff_http_auth_create_response(HTTPAuthState *state, const char *auth,
  99. const char *path, const char *method)
  100. {
  101. char *authstr = NULL;
  102. if (!auth || !strchr(auth, ':'))
  103. return NULL;
  104. if (state->auth_type == HTTP_AUTH_BASIC) {
  105. int auth_b64_len = (strlen(auth) + 2) / 3 * 4 + 1;
  106. int len = auth_b64_len + 30;
  107. char *ptr;
  108. authstr = av_malloc(len);
  109. if (!authstr)
  110. return NULL;
  111. snprintf(authstr, len, "Authorization: Basic ");
  112. ptr = authstr + strlen(authstr);
  113. av_base64_encode(ptr, auth_b64_len, auth, strlen(auth));
  114. av_strlcat(ptr, "\r\n", len);
  115. }
  116. return authstr;
  117. }