forked from FFmpeg/FFmpeg
133 lines
3.9 KiB
C
133 lines
3.9 KiB
C
![]() |
/*
|
||
|
* HTTP authentication
|
||
|
* Copyright (c) 2010 Martin Storsjo
|
||
|
*
|
||
|
* This file is part of FFmpeg.
|
||
|
*
|
||
|
* FFmpeg is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of the GNU Lesser General Public
|
||
|
* License as published by the Free Software Foundation; either
|
||
|
* version 2.1 of the License, or (at your option) any later version.
|
||
|
*
|
||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
* Lesser General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU Lesser General Public
|
||
|
* License along with FFmpeg; if not, write to the Free Software
|
||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||
|
*/
|
||
|
|
||
|
#include "httpauth.h"
|
||
|
#include "libavutil/base64.h"
|
||
|
#include "libavutil/avstring.h"
|
||
|
#include "avformat.h"
|
||
|
#include <ctype.h>
|
||
|
|
||
|
static void parse_key_value(const char *params,
|
||
|
void (*callback_get_buf)(HTTPAuthState *state,
|
||
|
const char *key, int key_len,
|
||
|
char **dest, int *dest_len), HTTPAuthState *state)
|
||
|
{
|
||
|
const char *ptr = params;
|
||
|
|
||
|
/* Parse key=value pairs. */
|
||
|
for (;;) {
|
||
|
const char *key;
|
||
|
char *dest = NULL, *dest_end;
|
||
|
int key_len, dest_len = 0;
|
||
|
|
||
|
/* Skip whitespace and potential commas. */
|
||
|
while (*ptr && (isspace(*ptr) || *ptr == ','))
|
||
|
ptr++;
|
||
|
if (!*ptr)
|
||
|
break;
|
||
|
|
||
|
key = ptr;
|
||
|
|
||
|
if (!(ptr = strchr(key, '=')))
|
||
|
break;
|
||
|
ptr++;
|
||
|
key_len = ptr - key;
|
||
|
|
||
|
callback_get_buf(state, key, key_len, &dest, &dest_len);
|
||
|
dest_end = dest + dest_len - 1;
|
||
|
|
||
|
if (*ptr == '\"') {
|
||
|
ptr++;
|
||
|
while (*ptr && *ptr != '\"') {
|
||
|
if (*ptr == '\\') {
|
||
|
if (!ptr[1])
|
||
|
break;
|
||
|
if (dest && dest < dest_end)
|
||
|
*dest++ = ptr[1];
|
||
|
ptr += 2;
|
||
|
} else {
|
||
|
if (dest && dest < dest_end)
|
||
|
*dest++ = *ptr;
|
||
|
ptr++;
|
||
|
}
|
||
|
}
|
||
|
if (*ptr == '\"')
|
||
|
ptr++;
|
||
|
} else {
|
||
|
for (; *ptr && !(isspace(*ptr) || *ptr == ','); ptr++)
|
||
|
if (dest && dest < dest_end)
|
||
|
*dest++ = *ptr;
|
||
|
}
|
||
|
if (dest)
|
||
|
*dest = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void handle_basic_params(HTTPAuthState *state, const char *key,
|
||
|
int key_len, char **dest, int *dest_len)
|
||
|
{
|
||
|
if (!strncmp(key, "realm=", key_len)) {
|
||
|
*dest = state->realm;
|
||
|
*dest_len = sizeof(state->realm);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ff_http_auth_handle_header(HTTPAuthState *state, const char *key,
|
||
|
const char *value)
|
||
|
{
|
||
|
if (!state)
|
||
|
return;
|
||
|
|
||
|
if (!strcmp(key, "WWW-Authenticate")) {
|
||
|
const char *p;
|
||
|
if (av_stristart(value, "Basic ", &p) &&
|
||
|
state->auth_type <= HTTP_AUTH_BASIC) {
|
||
|
state->auth_type = HTTP_AUTH_BASIC;
|
||
|
state->realm[0] = 0;
|
||
|
parse_key_value(p, handle_basic_params, state);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
char *ff_http_auth_create_response(HTTPAuthState *state, const char *auth,
|
||
|
const char *path, const char *method)
|
||
|
{
|
||
|
char *authstr = NULL;
|
||
|
|
||
|
if (!auth || !strchr(auth, ':'))
|
||
|
return NULL;
|
||
|
|
||
|
if (state->auth_type == HTTP_AUTH_BASIC) {
|
||
|
int auth_b64_len = (strlen(auth) + 2) / 3 * 4 + 1;
|
||
|
int len = auth_b64_len + 30;
|
||
|
char *ptr;
|
||
|
authstr = av_malloc(len);
|
||
|
if (!authstr)
|
||
|
return NULL;
|
||
|
snprintf(authstr, len, "Authorization: Basic ");
|
||
|
ptr = authstr + strlen(authstr);
|
||
|
av_base64_encode(ptr, auth_b64_len, auth, strlen(auth));
|
||
|
av_strlcat(ptr, "\r\n", len);
|
||
|
}
|
||
|
return authstr;
|
||
|
}
|
||
|
|