139 lines
3.3 KiB
C
139 lines
3.3 KiB
C
// This is a personal academic project. Dear PVS-Studio, please check it.
|
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "auth.h"
|
|
|
|
void auth_parser_init(struct auth_parser *p) {
|
|
p->state = auth_version;
|
|
p->remaining = 0;
|
|
}
|
|
|
|
enum auth_state auth_parser_feed(struct auth_parser * p, uint8_t b) {
|
|
switch (p->state) {
|
|
case auth_version:
|
|
if (0x01 == b) {
|
|
p->state = auth_ulen;
|
|
} else {
|
|
p->state = auth_error_unsupported_version;
|
|
}
|
|
break;
|
|
case auth_ulen:
|
|
p->remaining = b;
|
|
p->state = auth_uname;
|
|
|
|
if (p->remaining == 0) {
|
|
p->state = auth_plen;
|
|
}
|
|
break;
|
|
case auth_uname:
|
|
*(p->username + p->idx++) = (char) b;
|
|
p->remaining--;
|
|
|
|
if (p->remaining == 0) {
|
|
*(p->username + p->idx++) = 0;
|
|
if (NULL != p->on_username) {
|
|
p->on_username(p, p->username);
|
|
}
|
|
p->idx = 0;
|
|
p->state = auth_plen;
|
|
}
|
|
|
|
break;
|
|
case auth_plen:
|
|
p->remaining = b;
|
|
p->state = auth_passwd;
|
|
|
|
if (p->remaining == 0) {
|
|
p->state = auth_done;
|
|
}
|
|
break;
|
|
case auth_passwd:
|
|
*(p->password + p->idx++) = (char) b;
|
|
p->remaining--;
|
|
|
|
if (p->remaining == 0) {
|
|
*(p->password + p->idx++) = 0;
|
|
if (NULL != p->on_password) {
|
|
p->on_password(p, p->password);
|
|
}
|
|
p->idx = 0;
|
|
p->state = auth_done;
|
|
}
|
|
break;
|
|
case auth_done:
|
|
case auth_error_unsupported_version:
|
|
break;
|
|
default:
|
|
fprintf(stderr, "unknown state %d\n", p->state);
|
|
abort();
|
|
}
|
|
|
|
return p->state;
|
|
}
|
|
|
|
extern bool auth_is_done(const enum auth_state state, bool * errored) {
|
|
bool ret = true;
|
|
|
|
switch (state) {
|
|
case auth_error_unsupported_version:
|
|
if (0 != errored) {
|
|
*errored = true;
|
|
}
|
|
break;
|
|
case auth_done:
|
|
break;
|
|
default:
|
|
ret = false;
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
extern const char * auth_error(const struct auth_parser *p) {
|
|
char * ret;
|
|
switch (p->state) {
|
|
case auth_error_unsupported_version:
|
|
ret = "unsupported version";
|
|
break;
|
|
default:
|
|
ret = "";
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
extern void auth_parser_close(struct auth_parser * p) {}
|
|
|
|
|
|
extern enum auth_state auth_consume(buffer * b, struct auth_parser *p, bool * errored) {
|
|
enum auth_state st = p->state;
|
|
|
|
while (buffer_can_read(b)) {
|
|
const uint8_t c = buffer_read(b);
|
|
st = auth_parser_feed(p, c);
|
|
if (auth_is_done(st, errored)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return st;
|
|
}
|
|
|
|
extern int auth_marshall(buffer * b, const uint8_t status) {
|
|
size_t n;
|
|
uint8_t * buff = buffer_write_ptr(b, &n);
|
|
if (n < 2) {
|
|
return -1;
|
|
}
|
|
|
|
buff[0] = 0x01;
|
|
buff[1] = status;
|
|
|
|
buffer_write_adv(b, 2);
|
|
return 2;
|
|
}
|