Skip to content

Commit

Permalink
Handle invalid users and invalid passwords correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
haakonnessjoen committed Apr 6, 2024
1 parent ae46439 commit efbb349
Showing 1 changed file with 27 additions and 30 deletions.
57 changes: 27 additions & 30 deletions src/mactelnetd.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ struct mt_connection {
int pid;
int wait_for_ack;
int have_pass_salt;
int invalid_login;

char username[MT_MNDP_MAX_STRING_SIZE];
unsigned char trypassword[32];
Expand Down Expand Up @@ -392,14 +393,19 @@ static void user_login(struct mt_connection *curconn, struct mt_mactelnet_hdr *p
struct mt_packet pdata;
unsigned char hashsum[32];
char hashdata[100];
struct mt_credentials *user;
struct mt_credentials *user = NULL;
char *slavename;
int act_pass_len;

// In case we just got a duplicate login packet
if (curconn->state == STATE_ACTIVE) {
return;
}

/* Reparse user file before each login */
read_userfile();

if ((user = find_user(curconn->username)) != NULL) {
if (!curconn->invalid_login && (user = find_user(curconn->username)) != NULL) {
EVP_MD_CTX *context;
const EVP_MD *md;
unsigned int md_len;
Expand Down Expand Up @@ -434,16 +440,12 @@ static void user_login(struct mt_connection *curconn, struct mt_mactelnet_hdr *p
mtwei_id(curconn->username, user->password, curconn->pass_salt + MTWEI_PUBKEY_LEN, (uint8_t *)hashdata);
mtwei_docryptos(&mtwei, curconn->private_key, curconn->client_key, curconn->pass_salt, (uint8_t *)hashdata, hashsum);
}

init_packet(&pdata, MT_PTYPE_DATA, pkthdr->dstaddr, pkthdr->srcaddr, pkthdr->seskey, curconn->outcounter);
curconn->outcounter += add_control_packet(&pdata, MT_CPTYPE_END_AUTH, NULL, 0);
send_udp(curconn, &pdata);

if (curconn->state == STATE_ACTIVE) {
return;
}
}

init_packet(&pdata, MT_PTYPE_DATA, pkthdr->dstaddr, pkthdr->srcaddr, pkthdr->seskey, curconn->outcounter);
curconn->outcounter += add_control_packet(&pdata, MT_CPTYPE_END_AUTH, NULL, 0);
send_udp(curconn, &pdata);

if (user == NULL || memcmp(hashsum, curconn->trypassword, use_md5 ? 17 : 32) != 0) {
syslog(LOG_NOTICE, _("(%d) Invalid login by %s."), curconn->seskey, curconn->username);

Expand Down Expand Up @@ -627,7 +629,8 @@ static void handle_data_packet(struct mt_connection *curconn, struct mt_mactelne

send_udp(curconn, &pdata);

/* Don't change the username after the state is active */
} else if (use_md5 == 0 && cpkt.cptype == MT_CPTYPE_BEGINAUTH) {
/* Ignore, the client wil immediately send a passsalt/encryption key control packet after this */
} else if (use_md5 == 0 && cpkt.cptype == MT_CPTYPE_PASSSALT && curconn->state != STATE_ACTIVE && cpkt.length > MTWEI_PUBKEY_LEN + 1) {
strncpy(curconn->username, (const char *)cpkt.data, cpkt.length - MTWEI_PUBKEY_LEN);
if (cpkt.length - strlen(curconn->username) - 1 == MTWEI_PUBKEY_LEN) {
Expand All @@ -649,16 +652,20 @@ static void handle_data_packet(struct mt_connection *curconn, struct mt_mactelne
mtwei_id(curconn->username, user->password, curconn->pass_salt + MTWEI_PUBKEY_LEN, validator);
curconn->private_key = mtwei_keygen(&mtwei, curconn->pass_salt, validator);
} else {
syslog(LOG_NOTICE, _("(%d) Invalid login by %s."), curconn->seskey, curconn->username);
/* Continue auth flow, so we do not let an attacker figure out if the user exists or not */
curconn->have_pass_salt = 1;
curconn->invalid_login = 1;
}

init_packet(&pdata, MT_PTYPE_DATA, pkthdr->dstaddr, pkthdr->srcaddr, pkthdr->seskey, curconn->outcounter);
plen = add_control_packet(&pdata, MT_CPTYPE_PASSSALT, (curconn->pass_salt), user ? 49 : 33);
plen = add_control_packet(&pdata, MT_CPTYPE_PASSSALT, (curconn->pass_salt), 49);
curconn->outcounter += plen;

send_udp(curconn, &pdata);
} else {
syslog(LOG_NOTICE, _("(%d) Invalid mtwei key by %s."), curconn->seskey, curconn->username);
// Time out connection
curconn->state = STATE_CLOSED;
}

} else if (cpkt.cptype == MT_CPTYPE_USERNAME && curconn->state != STATE_ACTIVE) {
Expand All @@ -681,31 +688,23 @@ static void handle_data_packet(struct mt_connection *curconn, struct mt_mactelne
got_height_packet = 1;

} else if (cpkt.cptype == MT_CPTYPE_TERM_TYPE) {

memcpy(curconn->terminal_type, cpkt.data, act_size = (cpkt.length > 30 - 1 ? 30 - 1 : cpkt.length));
curconn->terminal_type[act_size] = 0;

} else if (cpkt.cptype == MT_CPTYPE_PASSWORD && cpkt.length == 17) {

} else if (cpkt.cptype == MT_CPTYPE_PASSWORD && (cpkt.length == 17 || cpkt.length == 32)) {
#if defined(_POSIX_MEMLOCK_RANGE) && _POSIX_MEMLOCK_RANGE > 0
mlock(curconn->trypassword, 17);
mlock(curconn->trypassword, cpkt.length);
#endif
memcpy(curconn->trypassword, cpkt.data, 17);
memcpy(curconn->trypassword, cpkt.data, cpkt.length);
got_pass_packet = 1;

} else if (cpkt.cptype == MT_CPTYPE_PASSWORD && cpkt.length == 32) {

#if defined(_POSIX_MEMLOCK_RANGE) && _POSIX_MEMLOCK_RANGE > 0
mlock(curconn->trypassword, 32);
#endif
memcpy(curconn->trypassword, cpkt.data, 32);
} else if (cpkt.cptype == MT_CPTYPE_PASSWORD && cpkt.length == 0) {
got_pass_packet = 1;

curconn->invalid_login = 1;
} else if (cpkt.cptype == MT_CPTYPE_PLAINDATA) {

/* relay data from client to shell */
if (curconn->state == STATE_ACTIVE && curconn->ptsfd != -1) {
write_wrapped(curconn->ptsfd, cpkt.data, cpkt.length);
write_wrapped(curconn->ptsfd, cpkt.data, cpkt.length);
}

} else {
Expand All @@ -722,7 +721,6 @@ static void handle_data_packet(struct mt_connection *curconn, struct mt_mactelne

if (curconn->state == STATE_ACTIVE && (got_width_packet || got_height_packet)) {
set_terminal_size(curconn->ptsfd, curconn->terminal_width, curconn->terminal_height);

}
}

Expand All @@ -744,7 +742,6 @@ static void handle_packet(unsigned char *data, int data_len, const struct sockad
}

switch (pkthdr.ptype) {

case MT_PTYPE_PING:
if (pings++ > MT_MAXPPS) {
/* Don't want it to wrap around back to the valid range */
Expand Down Expand Up @@ -851,7 +848,7 @@ static void handle_packet(unsigned char *data, int data_len, const struct sockad
init_packet(&pdata, MT_PTYPE_ACK, pkthdr.dstaddr, pkthdr.srcaddr, pkthdr.seskey, pkthdr.counter);
send_udp(curconn, &pdata);
}
}
}
if (0 && curconn != NULL) {
printf("Packet, incounter %d, outcounter %d\n", curconn->incounter, curconn->outcounter);
}
Expand Down

0 comments on commit efbb349

Please sign in to comment.