feat(restful): user password must be encrypted

This commit is contained in:
eeff
2024-05-30 21:10:57 +08:00
parent d1e0e0076d
commit 82e930c4b2
6 changed files with 123 additions and 20 deletions
+1
View File
@@ -49,6 +49,7 @@ typedef enum {
NEU_ERR_IP_ADDRESS_IN_USE = 1016,
NEU_ERR_WEAK_PASSWORD_ALPHABET = 1017,
NEU_ERR_WEAK_PASSWORD_PATTERN = 1018,
NEU_ERR_DECRYPT_PASSWORD_FAILED = 1019,
NEU_ERR_NODE_EXIST = 2002,
NEU_ERR_NODE_NOT_EXIST = 2003,
+25 -18
View File
@@ -53,23 +53,20 @@ void handle_login(nng_aio *aio)
NEU_PROCESS_HTTP_REQUEST(
aio, neu_json_login_req_t, neu_json_decode_login_req, {
neu_json_login_resp_t login_resp = { 0 };
neu_user_t * user = neu_load_user(req->name);
int pass_len = strlen(req->pass);
neu_user_t * user = NULL;
char *password = neu_decrypt_user_password(req->pass);
if (NULL == user) {
if (NULL == password) {
nlog_error("could not decrypt user `%s` password", req->name);
NEU_JSON_RESPONSE_ERROR(NEU_ERR_DECRYPT_PASSWORD_FAILED, {
neu_http_response(aio, error_code.error, result_error);
});
} else if (NULL == (user = neu_load_user(req->name))) {
nlog_error("could not find user `%s`", req->name);
NEU_JSON_RESPONSE_ERROR(NEU_ERR_INVALID_USER_OR_PASSWORD, {
neu_http_response(aio, error_code.error, result_error);
});
} else if (pass_len < NEU_USER_PASSWORD_MIN_LEN ||
pass_len > NEU_USER_PASSWORD_MAX_LEN) {
nlog_error("user `%s` password too short or too long",
req->name);
NEU_JSON_RESPONSE_ERROR(NEU_ERR_INVALID_PASSWORD_LEN, {
neu_http_response(aio, error_code.error, result_error);
});
} else if (neu_user_check_password(user, req->pass)) {
} else if (neu_user_check_password(user, password)) {
char *token = NULL;
char *result = NULL;
@@ -95,6 +92,7 @@ void handle_login(nng_aio *aio)
});
}
free(password);
neu_user_free(user);
})
}
@@ -105,21 +103,28 @@ void handle_password(nng_aio *aio)
aio, neu_json_password_req_t, neu_json_decode_password_req, {
neu_user_t *user = NULL;
int rv = 0;
int pass_len = strlen(req->new_pass);
char * new_pass = neu_decrypt_user_password(req->new_pass);
char * old_pass = neu_decrypt_user_password(req->old_pass);
int pass_len = new_pass ? strlen(new_pass) : 0;
if (pass_len < NEU_USER_PASSWORD_MIN_LEN ||
pass_len > NEU_USER_PASSWORD_MAX_LEN) {
if (NULL == new_pass) {
nlog_error("could not decrypt user `%s` new pass", req->name);
rv = NEU_ERR_DECRYPT_PASSWORD_FAILED;
} else if (NULL == old_pass) {
nlog_error("could not decrypt user `%s` old pass", req->name);
rv = NEU_ERR_DECRYPT_PASSWORD_FAILED;
} else if (pass_len < NEU_USER_PASSWORD_MIN_LEN ||
pass_len > NEU_USER_PASSWORD_MAX_LEN) {
nlog_error("user `%s` new password too short or too long",
req->name);
rv = NEU_ERR_INVALID_PASSWORD_LEN;
} else if (NULL == (user = neu_load_user(req->name))) {
nlog_error("could not find user `%s`", req->name);
rv = NEU_ERR_INVALID_USER_OR_PASSWORD;
} else if (!neu_user_check_password(user, req->old_pass)) {
} else if (!neu_user_check_password(user, old_pass)) {
nlog_error("user `%s` password check fail", req->name);
rv = NEU_ERR_INVALID_USER_OR_PASSWORD;
} else if (0 !=
(rv = neu_user_update_password(user, req->new_pass))) {
} else if (0 != (rv = neu_user_update_password(user, new_pass))) {
nlog_error("user `%s` update password fail", req->name);
} else if (0 != (rv = neu_save_user(user))) {
nlog_error("user `%s` persist fail", req->name);
@@ -129,6 +134,8 @@ void handle_password(nng_aio *aio)
neu_http_response(aio, error_code.error, result_error);
});
free(new_pass);
free(old_pass);
neu_user_free(user);
})
}
+88
View File
@@ -11,6 +11,7 @@
#include "errcodes.h"
#include "user.h"
#include "utils/base64.h"
#include "utils/log.h"
static const unsigned char cov_2char[64] = {
@@ -438,6 +439,93 @@ static inline int checkout_password_strength(const char *password)
return 0;
}
static inline EVP_CIPHER_CTX *aes_ctx_new()
{
int ret = 0;
unsigned char key[32] = { 90, 45, 54, 10, 182, 19, 52, 130,
109, 151, 202, 252, 248, 177, 136, 35,
234, 204, 188, 2, 72, 215, 207, 52,
22, 5, 193, 52, 228, 224, 157, 28 };
unsigned char iv[16] = { 239, 227, 132, 238, 4, 225, 127, 67,
202, 77, 31, 79, 203, 70, 149, 132 };
EVP_CIPHER_CTX *e = EVP_CIPHER_CTX_new();
if (NULL == e) {
return NULL;
}
EVP_CIPHER_CTX_init(e);
ret = EVP_DecryptInit_ex(e, EVP_aes_256_cbc(), NULL, key, iv);
if (0 == ret) {
EVP_CIPHER_CTX_free(e);
return NULL;
}
return e;
}
static char *aes_decrypt(unsigned char *cipher_text, int *len)
{
char *plain_text = NULL;
int plain_text_len = *len + EVP_CIPHER_block_size(EVP_aes_256_cbc());
int f_len = 0;
int ret = 0;
EVP_CIPHER_CTX *ctx = aes_ctx_new();
if (NULL == ctx) {
nlog_warn("alloc ctx fail");
return NULL;
}
plain_text = calloc(1, plain_text_len + 1);
if (NULL == plain_text) {
nlog_warn("alloc plain_text fail");
return NULL;
}
ret = EVP_DecryptUpdate(ctx, (unsigned char *) plain_text, &plain_text_len,
(unsigned char *) cipher_text, *len);
if (ret <= 0) {
free(plain_text);
EVP_CIPHER_CTX_free(ctx);
nlog_warn("decrypt update error: %d", ret);
return NULL;
}
ret = EVP_DecryptFinal_ex(
ctx, (unsigned char *) plain_text + plain_text_len, &f_len);
if (ret <= 0) {
free(plain_text);
EVP_CIPHER_CTX_free(ctx);
nlog_warn("decrypt final error: %d", ret);
return NULL;
}
*len = plain_text_len + f_len;
EVP_CIPHER_CTX_free(ctx);
return plain_text;
}
char *neu_decrypt_user_password(const char *crypted_password)
{
int len = 0;
char * password = NULL;
unsigned char *cipher_text = neu_decode64(&len, crypted_password);
if (cipher_text && (password = aes_decrypt(cipher_text, &len))) {
password[len] = '\0';
for (int i = 0; i < len; ++i) {
if ('\0' == password[i]) {
free(password);
password = NULL;
}
}
}
free(cipher_text);
return password;
}
neu_user_t *neu_user_new(const char *name, const char *password)
{
neu_user_t *user = malloc(sizeof(*user));
+2
View File
@@ -41,6 +41,8 @@ int neu_user_update_password(neu_user_t *user, const char *new_password);
neu_user_t *neu_load_user(const char *name);
int neu_save_user(neu_user_t *user);
char *neu_decrypt_user_password(const char *crypted_password);
#ifdef __cplusplus
}
#endif
+6 -2
View File
@@ -68,10 +68,14 @@ int Base64Decode(const char *b64message, unsigned char **buffer, int *length)
BIO_set_flags(
bio, BIO_FLAGS_BASE64_NO_NL); // Do not use newlines to flush buffer
*length = BIO_read(bio, *buffer, strlen(b64message));
assert(*length == decodeLen); // length should equal decodeLen, else
// something went horribly wrong
BIO_free_all(bio);
if (*length != decodeLen) {
free(*buffer);
*buffer = NULL;
return -1;
}
return (0); // success
}
+1
View File
@@ -340,6 +340,7 @@ int neu_http_response(nng_aio *aio, neu_err_code_e code, char *content)
case NEU_ERR_DUPLICATE_PASSWORD:
case NEU_ERR_WEAK_PASSWORD_ALPHABET:
case NEU_ERR_WEAK_PASSWORD_PATTERN:
case NEU_ERR_DECRYPT_PASSWORD_FAILED:
case NEU_ERR_TEMPLATE_NAME_TOO_LONG:
case NEU_ERR_PLUGIN_NAME_TOO_LONG:
case NEU_ERR_PLUGIN_NOT_SUPPORT_TEMPLATE: