264 lines
7.3 KiB
C
264 lines
7.3 KiB
C
#include "links.h"
|
|
|
|
static struct list_head auth = {&auth, &auth};
|
|
|
|
struct http_auth {
|
|
list_entry_1st
|
|
unsigned char *host;
|
|
int port;
|
|
unsigned char *realm;
|
|
unsigned char *user;
|
|
unsigned char *password;
|
|
unsigned char *directory;
|
|
unsigned char *user_password_encoded;
|
|
int proxy;
|
|
list_entry_last
|
|
};
|
|
|
|
static_const unsigned char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
|
|
unsigned char *base64_encode(unsigned char *in, int inlen, unsigned char *prefix, unsigned char *suffix, int line_bits)
|
|
{
|
|
unsigned char *out, *outstr;
|
|
int data_len;
|
|
int line_mask = ~0;
|
|
int col;
|
|
int prefix_len = (int)strlen(cast_const_char prefix);
|
|
int suffix_len = (int)strlen(cast_const_char suffix);
|
|
if (inlen > MAXINT / 2) overalloc();
|
|
data_len = ((inlen + 2) / 3) * 4;
|
|
if (line_bits >= 0) {
|
|
line_mask = (1 << line_bits) - 1;
|
|
data_len += (data_len + line_mask) >> line_bits;
|
|
}
|
|
outstr = mem_alloc(prefix_len + data_len + suffix_len + 1);
|
|
memcpy(outstr, prefix, prefix_len);
|
|
out = outstr + prefix_len;
|
|
col = 0;
|
|
while (inlen >= 3) {
|
|
*out++ = base64_chars[ (int)(in[0] >> 2) ];
|
|
*out++ = base64_chars[ (int)((in[0] << 4 | in[1] >> 4) & 63) ];
|
|
*out++ = base64_chars[ (int)((in[1] << 2 | in[2] >> 6) & 63) ];
|
|
*out++ = base64_chars[ (int)(in[2] & 63) ];
|
|
inlen -= 3; in += 3;
|
|
if (!((col += 4) & line_mask))
|
|
*out++ = '\n';
|
|
}
|
|
if (inlen == 1) {
|
|
*out++ = base64_chars[ (int)(in[0] >> 2) ];
|
|
*out++ = base64_chars[ (int)(in[0] << 4 & 63) ];
|
|
*out++ = '=';
|
|
*out++ = '=';
|
|
}
|
|
if (inlen == 2) {
|
|
*out++ = base64_chars[ (int)(in[0] >> 2) ];
|
|
*out++ = base64_chars[ (int)((in[0] << 4 | in[1] >> 4) & 63) ];
|
|
*out++ = base64_chars[ (int)((in[1] << 2) & 63) ];
|
|
*out++ = '=';
|
|
}
|
|
if (line_bits >= 0 && out > outstr + prefix_len && out[-1] != '\n')
|
|
*out++ = '\n';
|
|
strcpy(cast_char out, cast_const_char suffix);
|
|
/*fprintf(stderr, "%d - %d = %d\n", prefix_len + data_len + suffix_len + 1, strlen(cast_const_char outstr) + 1, prefix_len + data_len + suffix_len - strlen(cast_const_char outstr));*/
|
|
return outstr;
|
|
}
|
|
|
|
static unsigned char *basic_encode(unsigned char *user, unsigned char *password)
|
|
{
|
|
unsigned char *e, *p;
|
|
p = stracpy(user);
|
|
add_to_strn(&p, cast_uchar ":");
|
|
add_to_strn(&p, password);
|
|
e = base64_encode(p, (int)strlen(cast_const_char p), cast_uchar "", cast_uchar "", -1);
|
|
mem_free(p);
|
|
return e;
|
|
}
|
|
|
|
unsigned char *get_auth_realm(unsigned char *url, unsigned char *head, int proxy)
|
|
{
|
|
unsigned char *ch = head;
|
|
unsigned char *h, *q, *r;
|
|
int l;
|
|
int unknown = 0;
|
|
int known = 0;
|
|
try_next:
|
|
h = parse_http_header(ch, !proxy ? (unsigned char *)"WWW-Authenticate" : (unsigned char *)"Proxy-Authenticate", &ch);
|
|
if (!h) {
|
|
if (unknown && !known) return NULL;
|
|
if (proxy) {
|
|
unsigned char *p = get_proxy_string(url);
|
|
if (!p) p = cast_uchar "";
|
|
return stracpy(p);
|
|
} else {
|
|
unsigned char *u = get_host_name(url);
|
|
if (u) return u;
|
|
return stracpy(cast_uchar "");
|
|
}
|
|
}
|
|
if (casecmp(h, cast_uchar "Basic", 5)) {
|
|
mem_free(h);
|
|
unknown = 1;
|
|
goto try_next;
|
|
}
|
|
known = 1;
|
|
q = cast_uchar strchr(cast_const_char h, '"');
|
|
if (!q) {
|
|
mem_free(h);
|
|
goto try_next;
|
|
}
|
|
q++;
|
|
r = init_str();
|
|
l = 0;
|
|
while (*q && *q != '"') {
|
|
if (*q == '\\' && !*++q) break;
|
|
add_chr_to_str(&r, &l, *q++);
|
|
}
|
|
mem_free(h);
|
|
return r;
|
|
}
|
|
|
|
static unsigned char *auth_from_url(unsigned char *url, int proxy)
|
|
{
|
|
unsigned char *r = NULL;
|
|
int l = 0;
|
|
unsigned char *user, *password;
|
|
|
|
user = get_user_name(url);
|
|
password = get_pass(url);
|
|
if (user && *user && password) {
|
|
unsigned char *e = basic_encode(user, password);
|
|
r = init_str();
|
|
if (proxy) add_to_str(&r, &l, cast_uchar "Proxy-");
|
|
add_to_str(&r, &l, cast_uchar "Authorization: Basic ");
|
|
add_to_str(&r, &l, e);
|
|
add_to_str(&r, &l, cast_uchar "\r\n");
|
|
mem_free(e);
|
|
if (user) mem_free(user);
|
|
if (password) mem_free(password);
|
|
return r;
|
|
}
|
|
if (user) mem_free(user);
|
|
if (password) mem_free(password);
|
|
return NULL;
|
|
}
|
|
|
|
unsigned char *get_auth_string(unsigned char *url, int proxy)
|
|
{
|
|
struct http_auth *a;
|
|
struct list_head *la;
|
|
unsigned char *host;
|
|
int port;
|
|
unsigned char *r = NULL;
|
|
int l = 0;
|
|
if (proxy && !is_proxy_url(url)) return NULL;
|
|
if (!(host = get_host_name(url))) return NULL;
|
|
port = get_port(url);
|
|
|
|
if (!proxy && (r = auth_from_url(url, proxy))) goto have_passwd;
|
|
|
|
foreach(struct http_auth, a, la, auth) if (a->proxy == proxy && !casestrcmp(a->host, host) && a->port == port) {
|
|
unsigned char *d, *data;
|
|
if (proxy) goto skip_dir_check;
|
|
data = get_url_data(url);
|
|
d = cast_uchar strrchr(cast_const_char data, '/');
|
|
if (!d) d = data;
|
|
else d++;
|
|
if ((size_t)(d - data) >= strlen(cast_const_char a->directory) && !memcmp(data, a->directory, strlen(cast_const_char a->directory))) {
|
|
skip_dir_check:
|
|
r = init_str();
|
|
if (proxy) add_to_str(&r, &l, cast_uchar "Proxy-");
|
|
add_to_str(&r, &l, cast_uchar "Authorization: Basic ");
|
|
add_to_str(&r, &l, a->user_password_encoded);
|
|
add_to_str(&r, &l, cast_uchar "\r\n");
|
|
goto have_passwd;
|
|
}
|
|
}
|
|
|
|
if (proxy && (r = auth_from_url(url, proxy))) goto have_passwd;
|
|
|
|
have_passwd:
|
|
mem_free(host);
|
|
return r;
|
|
}
|
|
|
|
static void free_auth_entry(struct http_auth *a)
|
|
{
|
|
mem_free(a->host);
|
|
mem_free(a->realm);
|
|
mem_free(a->user);
|
|
mem_free(a->password);
|
|
if (a->directory) mem_free(a->directory);
|
|
mem_free(a->user_password_encoded);
|
|
del_from_list(a);
|
|
mem_free(a);
|
|
}
|
|
|
|
void free_auth(void)
|
|
{
|
|
while (!list_empty(auth)) free_auth_entry(list_struct(auth.next, struct http_auth));
|
|
}
|
|
|
|
void add_auth(unsigned char *url, unsigned char *realm, unsigned char *user, unsigned char *password, int proxy)
|
|
{
|
|
struct http_auth *a;
|
|
struct list_head *la;
|
|
unsigned char *host = NULL;
|
|
int port = 0 /* against warning */;
|
|
if (!proxy) {
|
|
host = get_host_name(url);
|
|
port = get_port(url);
|
|
} else {
|
|
unsigned char *p = get_proxy(url);
|
|
if (strcmp(cast_const_char p, cast_const_char url)) {
|
|
host = get_host_name(p);
|
|
port = get_port(p);
|
|
}
|
|
mem_free(p);
|
|
}
|
|
if (!host) return;
|
|
foreach(struct http_auth, a, la, auth) if (a->proxy == proxy && !casestrcmp(a->host, host) && a->port == port && !strcmp(cast_const_char a->realm, cast_const_char realm)) {
|
|
la = la->prev;
|
|
free_auth_entry(a);
|
|
}
|
|
a = mem_alloc(sizeof(struct http_auth));
|
|
a->host = host;
|
|
a->port = port;
|
|
a->realm = stracpy(realm);
|
|
a->user = stracpy(user);
|
|
a->password = stracpy(password);
|
|
if (!proxy) {
|
|
unsigned char *data = stracpy(get_url_data(url));
|
|
unsigned char *d = cast_uchar strrchr(cast_const_char data, '/');
|
|
if (d) d[1] = 0;
|
|
else data[0] = 0;
|
|
a->directory = data;
|
|
} else a->directory = NULL;
|
|
a->proxy = proxy;
|
|
a->user_password_encoded = basic_encode(a->user, a->password);
|
|
add_to_list(auth, a);
|
|
}
|
|
|
|
int find_auth(unsigned char *url, unsigned char *realm)
|
|
{
|
|
struct http_auth *a;
|
|
struct list_head *la;
|
|
unsigned char *data, *d;
|
|
unsigned char *host = get_host_name(url);
|
|
int port = get_port(url);
|
|
if (!host) return -1;
|
|
data = stracpy(get_url_data(url));
|
|
d = cast_uchar strrchr(cast_const_char data, '/');
|
|
if (d) d[1] = 0;
|
|
foreach(struct http_auth, a, la, auth) if (!a->proxy && !casestrcmp(a->host, host) && a->port == port && !strcmp(cast_const_char a->realm, cast_const_char realm) && strcmp(cast_const_char a->directory, cast_const_char data)) {
|
|
mem_free(a->directory);
|
|
a->directory = data;
|
|
mem_free(host);
|
|
del_from_list(a);
|
|
add_to_list(auth, a);
|
|
return 0;
|
|
}
|
|
mem_free(host);
|
|
mem_free(data);
|
|
return -1;
|
|
}
|
|
|