Add api_cmd_encrypt and use in api_init_encrypt
This commit is contained in:
parent
6cf62ab039
commit
605f47f761
@ -34,7 +34,6 @@ make
|
|||||||
- Make deleting from mylist possible, with
|
- Make deleting from mylist possible, with
|
||||||
- Name regexes,
|
- Name regexes,
|
||||||
- If file is not found at a scan
|
- If file is not found at a scan
|
||||||
- Use api\_cmd style in api\_encrypt\_init
|
|
||||||
- Buffer up mylistadd api cmds when waiting for ratelimit
|
- Buffer up mylistadd api cmds when waiting for ratelimit
|
||||||
- Handle C-c gracefully at any time
|
- Handle C-c gracefully at any time
|
||||||
- Write -h page, and maybe a man page too
|
- Write -h page, and maybe a man page too
|
||||||
|
116
src/api.c
116
src/api.c
@ -44,6 +44,7 @@
|
|||||||
static enum error api_cmd_logout(struct api_result *res);
|
static enum error api_cmd_logout(struct api_result *res);
|
||||||
static enum error api_cmd_auth(const char *uname, const char *pass,
|
static enum error api_cmd_auth(const char *uname, const char *pass,
|
||||||
struct api_result *res);
|
struct api_result *res);
|
||||||
|
static enum error api_cmd_encrypt(const char *uname, struct api_result *res);
|
||||||
|
|
||||||
static bool api_authed = false;
|
static bool api_authed = false;
|
||||||
static char api_session[API_SMAXSIZE] = {0}; /* No escaping is needed */
|
static char api_session[API_SMAXSIZE] = {0}; /* No escaping is needed */
|
||||||
@ -94,41 +95,44 @@ static int api_escaped_sring_info(const struct printf_info *info, size_t n,
|
|||||||
|
|
||||||
static enum error api_init_encrypt(const char *api_key, const char *uname)
|
static enum error api_init_encrypt(const char *api_key, const char *uname)
|
||||||
{
|
{
|
||||||
char buffer[API_BUFSIZE];
|
|
||||||
MD5Context md5_ctx;
|
MD5Context md5_ctx;
|
||||||
char *salt_start = buffer + 4 /* 209 [salt here] ... */, *salt_end;
|
struct api_result res;
|
||||||
ssize_t r_len, salt_len;
|
enum error err;
|
||||||
|
size_t salt_len;
|
||||||
|
|
||||||
if (net_send(buffer, snprintf(buffer, sizeof(buffer),
|
if (api_cmd_encrypt(uname, &res) != NOERR)
|
||||||
"ENCRYPT user=%s&type=1", uname)) == -1) {
|
|
||||||
return ERR_API_COMMFAIL;
|
|
||||||
}
|
|
||||||
r_len = net_read(buffer, sizeof(buffer));
|
|
||||||
|
|
||||||
if (strncmp(buffer, "209", 3) != 0) {
|
|
||||||
uio_error("We expected 209 response, but got: %.*s",
|
|
||||||
(int)r_len, buffer);
|
|
||||||
return ERR_API_ENCRYPTFAIL;
|
return ERR_API_ENCRYPTFAIL;
|
||||||
}
|
|
||||||
|
|
||||||
salt_end = strchr(salt_start, ' ');
|
if (res.code != 209) {
|
||||||
if (!salt_end) {
|
err = ERR_API_ENCRYPTFAIL;
|
||||||
uio_error("Cannot find space after salt in response");
|
switch (res.code) {
|
||||||
return ERR_API_ENCRYPTFAIL;
|
case 309:
|
||||||
|
uio_error("You'r API key is not defined. Define it here: "
|
||||||
|
"http://anidb.net/perl-bin/animedb.pl?show=profile");
|
||||||
|
break;
|
||||||
|
case 509:
|
||||||
|
uio_error("No such encryption type. Maybe client is outdated?");
|
||||||
|
break;
|
||||||
|
case 394:
|
||||||
|
uio_error("No user with name: '%s' found by AniDB", uname);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
uio_error("Unknown encrypt failure: %ld", res.code);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
salt_len = salt_end - salt_start;
|
salt_len = strlen(res.encrypt.salt);
|
||||||
|
|
||||||
md5Init(&md5_ctx);
|
md5Init(&md5_ctx);
|
||||||
md5Update(&md5_ctx, (uint8_t*)api_key, strlen(api_key));
|
md5Update(&md5_ctx, (uint8_t*)api_key, strlen(api_key));
|
||||||
md5Update(&md5_ctx, (uint8_t*)salt_start, salt_len);
|
md5Update(&md5_ctx, (uint8_t*)res.encrypt.salt, salt_len);
|
||||||
md5Finalize(&md5_ctx);
|
md5Finalize(&md5_ctx);
|
||||||
memcpy(e_key, md5_ctx.digest, sizeof(e_key));
|
memcpy(e_key, md5_ctx.digest, sizeof(e_key));
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
char *buffpos = buffer;
|
char bf[sizeof(e_key) * 2 + 1];
|
||||||
for (int i = 0; i < 16; i++)
|
util_byte2hex(e_key, sizeof(e_key), false, bf);
|
||||||
buffpos += sprintf(buffpos, "%02x", e_key[i]);
|
uio_debug("Encryption key is: '%s'", bf);
|
||||||
uio_debug("Encryption key is: '%s'", buffer);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
api_encryption = true;
|
api_encryption = true;
|
||||||
@ -497,11 +501,11 @@ static ssize_t api_send(char *buffer, size_t data_len, size_t buf_size)
|
|||||||
read_len = net_read(buffer, buf_size);
|
read_len = net_read(buffer, buf_size);
|
||||||
if (read_len < 0) {
|
if (read_len < 0) {
|
||||||
uio_error("!!! BAD PLACE EINTR !!! report pls");
|
uio_error("!!! BAD PLACE EINTR !!! report pls");
|
||||||
return en; /* This could lead so some problems if we also want to
|
return read_len; /* This could lead so some problems if we also want to
|
||||||
log out. If we hit this, the msg got sent, but we
|
log out. If we hit this, the msg got sent, but we
|
||||||
couldn't read the response. That means, in the
|
couldn't read the response. That means, in the
|
||||||
logout call, this msg's data will be read
|
logout call, this msg's data will be read
|
||||||
Let's see if this ever comes up */
|
Let's see if this ever comes up */
|
||||||
}
|
}
|
||||||
api_ratelimit_sent();
|
api_ratelimit_sent();
|
||||||
|
|
||||||
@ -573,10 +577,54 @@ static char *api_get_field_mod(char *buffer, int32_t field_num)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static enum error api_cmd_encrypt(const char *uname, struct api_result *res)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&api_work_mx);
|
||||||
|
char buffer[API_BUFSIZE];
|
||||||
|
long code;
|
||||||
|
enum error err = NOERR;
|
||||||
|
/* Usernames can't contain '&' */
|
||||||
|
ssize_t res_len = api_send(buffer, snprintf(buffer, sizeof(buffer),
|
||||||
|
"ENCRYPT user=%s&type=1", uname),
|
||||||
|
sizeof(buffer));
|
||||||
|
|
||||||
|
if (res_len < 0) {
|
||||||
|
if (res_len == -2 && should_exit)
|
||||||
|
err = ERR_SHOULD_EXIT;
|
||||||
|
else
|
||||||
|
err = ERR_API_COMMFAIL;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
code = api_res_code(buffer);
|
||||||
|
if (code == -1) {
|
||||||
|
err = ERR_API_RESP_INVALID;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (code == 209) {
|
||||||
|
char *fs;
|
||||||
|
size_t fl;
|
||||||
|
bool gfl = api_get_field(buffer, 2, &fs, &fl);
|
||||||
|
|
||||||
|
assert(gfl);
|
||||||
|
(void)gfl;
|
||||||
|
assert(sizeof(res->encrypt.salt) > fl);
|
||||||
|
memcpy(res->encrypt.salt, fs, fl);
|
||||||
|
res->encrypt.salt[fl] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
res->code = (uint16_t)code;
|
||||||
|
|
||||||
|
end:
|
||||||
|
pthread_mutex_unlock(&api_work_mx);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
enum error api_cmd_version(struct api_result *res)
|
enum error api_cmd_version(struct api_result *res)
|
||||||
{
|
{
|
||||||
char buffer[API_BUFSIZE] = "VERSION";
|
char buffer[API_BUFSIZE] = "VERSION";
|
||||||
size_t res_len = api_send(buffer, strlen(buffer), sizeof(buffer));
|
ssize_t res_len = api_send(buffer, strlen(buffer), sizeof(buffer));
|
||||||
long code;
|
long code;
|
||||||
enum error err = NOERR;
|
enum error err = NOERR;
|
||||||
pthread_mutex_lock(&api_work_mx);
|
pthread_mutex_lock(&api_work_mx);
|
||||||
@ -619,11 +667,11 @@ static enum error api_cmd_auth(const char *uname, const char *pass,
|
|||||||
pthread_mutex_lock(&api_work_mx);
|
pthread_mutex_lock(&api_work_mx);
|
||||||
char buffer[API_BUFSIZE];
|
char buffer[API_BUFSIZE];
|
||||||
long code;
|
long code;
|
||||||
size_t res_len = api_send(buffer, snprintf(buffer, sizeof(buffer),
|
enum error err = NOERR;
|
||||||
|
ssize_t res_len = api_send(buffer, snprintf(buffer, sizeof(buffer),
|
||||||
"AUTH user=%s&pass=%B&protover=" API_VERSION "&client=caniadd&"
|
"AUTH user=%s&pass=%B&protover=" API_VERSION "&client=caniadd&"
|
||||||
"clientver=" PROG_VERSION "&enc=UTF-8", uname, pass),
|
"clientver=" PROG_VERSION "&enc=UTF-8", uname, pass),
|
||||||
sizeof(buffer));
|
sizeof(buffer));
|
||||||
enum error err = NOERR;
|
|
||||||
|
|
||||||
if (res_len < 0) {
|
if (res_len < 0) {
|
||||||
if (res_len == -2 && should_exit)
|
if (res_len == -2 && should_exit)
|
||||||
@ -669,7 +717,7 @@ static enum error api_cmd_logout(struct api_result *res)
|
|||||||
{
|
{
|
||||||
pthread_mutex_lock(&api_work_mx);
|
pthread_mutex_lock(&api_work_mx);
|
||||||
char buffer[API_BUFSIZE];
|
char buffer[API_BUFSIZE];
|
||||||
size_t res_len = api_send(buffer, snprintf(buffer, sizeof(buffer),
|
ssize_t res_len = api_send(buffer, snprintf(buffer, sizeof(buffer),
|
||||||
"LOGOUT s=%s", api_session), sizeof(buffer));
|
"LOGOUT s=%s", api_session), sizeof(buffer));
|
||||||
long code;
|
long code;
|
||||||
enum error err = NOERR;
|
enum error err = NOERR;
|
||||||
@ -702,7 +750,7 @@ enum error api_cmd_uptime(struct api_result *res)
|
|||||||
if (!api_ka_now)
|
if (!api_ka_now)
|
||||||
pthread_mutex_lock(&api_work_mx);
|
pthread_mutex_lock(&api_work_mx);
|
||||||
char buffer[API_BUFSIZE];
|
char buffer[API_BUFSIZE];
|
||||||
size_t res_len = api_send(buffer, snprintf(buffer, sizeof(buffer),
|
ssize_t res_len = api_send(buffer, snprintf(buffer, sizeof(buffer),
|
||||||
"UPTIME s=%s", api_session), sizeof(buffer));
|
"UPTIME s=%s", api_session), sizeof(buffer));
|
||||||
long code;
|
long code;
|
||||||
enum error err = NOERR;
|
enum error err = NOERR;
|
||||||
@ -744,7 +792,7 @@ enum error api_cmd_mylistadd(int64_t size, const uint8_t *hash,
|
|||||||
{
|
{
|
||||||
char buffer[API_BUFSIZE];
|
char buffer[API_BUFSIZE];
|
||||||
char hash_str[ED2K_HASH_SIZE * 2 + 1];
|
char hash_str[ED2K_HASH_SIZE * 2 + 1];
|
||||||
size_t res_len;
|
ssize_t res_len;
|
||||||
enum error err = NOERR;
|
enum error err = NOERR;
|
||||||
long code;
|
long code;
|
||||||
pthread_mutex_lock(&api_work_mx);
|
pthread_mutex_lock(&api_work_mx);
|
||||||
|
@ -11,9 +11,11 @@
|
|||||||
#define API_BUFSIZE 1400
|
#define API_BUFSIZE 1400
|
||||||
/* Session key maximum size, including '\0' */
|
/* Session key maximum size, including '\0' */
|
||||||
#define API_SMAXSIZE 16
|
#define API_SMAXSIZE 16
|
||||||
|
/* Encryption salt maximum size, including '\0' */
|
||||||
|
#define API_SALTMAXSIZE 16
|
||||||
|
|
||||||
/* The session timeout in miliseconds */
|
/* The session timeout in miliseconds */
|
||||||
#define API_TIMEOUT 30 * 60 * 1000
|
#define API_TIMEOUT 30 * 60 * 1000
|
||||||
|
|
||||||
/* How many miliseconds to wait between sends */
|
/* How many miliseconds to wait between sends */
|
||||||
#define API_SENDWAIT 2 * 1000
|
#define API_SENDWAIT 2 * 1000
|
||||||
/* The number of packets that are exccempt from the ratelimit */
|
/* The number of packets that are exccempt from the ratelimit */
|
||||||
@ -54,6 +56,9 @@ struct api_auth_result {
|
|||||||
char *banned_reason;
|
char *banned_reason;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
struct api_encrypt_result {
|
||||||
|
char salt[API_SALTMAXSIZE];
|
||||||
|
};
|
||||||
struct api_uptime_result {
|
struct api_uptime_result {
|
||||||
int32_t ms;
|
int32_t ms;
|
||||||
};
|
};
|
||||||
@ -78,6 +83,7 @@ struct api_result {
|
|||||||
struct api_auth_result auth;
|
struct api_auth_result auth;
|
||||||
struct api_uptime_result uptime;
|
struct api_uptime_result uptime;
|
||||||
e(mylistadd);
|
e(mylistadd);
|
||||||
|
e(encrypt);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
#undef e
|
#undef e
|
||||||
|
Loading…
Reference in New Issue
Block a user