Rev 6 | Rev 8 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
/* $Id: crypt.c 7 2024-09-25 00:56:55Z nishi $ */
#include "cm_crypt.h"
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __linux__
#include <crypt.h>
#endif
const char* cm_crypt_methods[] = {"DES", "MD5", "Blowfish", "", "", "SHA-256", "SHA-512",
#ifdef __NetBSD__
"Argon2",
#endif
NULL};
char* cm_crypt_spec(int num, const char* string, const char* salt) {
char* r = NULL;
if(num == C_DES) {
r = crypt(string, salt);
} else if(num == C_MD5 || num == C_SHA256 || num == C_SHA512) {
char* buffer = malloc(3 + strlen(salt) + 1 + 1);
buffer[3 + strlen(salt) + 1] = 0;
sprintf(buffer, "$%d$%s$", num, salt);
r = crypt(string, buffer);
free(buffer);
} else if(num == C_BLOWFISH) {
char* buffer = malloc(4 + 3 + strlen(salt) + 1 + 1);
buffer[4 + 3 + strlen(salt) + 1] = 0;
sprintf(buffer, "$%da$08$%s$", num, salt);
r = crypt(string, buffer);
free(buffer);
} else if(num == C_ARGON2) {
if(strlen(salt) != 16) return NULL;
char* buffer = malloc(1 + 8 + 1 + 4 + 1 + 16 + 1 + 1 + 7);
buffer[1 + 8 + 1 + 4 + 1 + 16 + 1 + 7] = 0;
sprintf(buffer, "$argon2id$v=19$m=4096$%s$", salt);
r = crypt(string, buffer);
free(buffer);
}
if(r == NULL || strcmp(r, "*0") == 0 || strcmp(r, ":") == 0) r = NULL;
return r;
}
int cm_crypt_try(int num) {
printf("Trying %s... ", cm_crypt_methods[num]);
fflush(stdout);
if(cm_crypt_spec(num, "random", "randomrandomrandomrandom") != NULL) {
printf("works\n");
return 1;
}
#ifdef __NetBSD__
if(cm_crypt_spec(num, "random", "abcdabcdabcdabcd") != NULL) {
printf("works\n");
return 1;
}
#endif
printf("does not work\n");
return 0;
}
int cm_chosen_crypt;
int cm_crypt_init(void) {
int i;
int last = -1;
for(i = C_START + 1; i < C_END; i++) {
if(strlen(cm_crypt_methods[i]) != 0) {
if(cm_crypt_try(i)) {
last = i;
}
}
}
cm_chosen_crypt = last;
return last;
}
char* cm_crypt(const char* string) {
char salt[65];
salt[64] = 0;
int i;
FILE* f = fopen("/dev/urandom", "rb");
unsigned char c;
const char usable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
for(i = 0; i < 64; i++) {
fread(&c, 1, 1, f);
salt[i] = c % strlen(usable);
}
fclose(f);
return cm_crypt_spec(cm_chosen_crypt, string, salt);
}