Subversion Repositories MLServ

Rev

Rev 8 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5 nishi 1
/* $Id: crypt.c 9 2024-09-25 01:17:09Z nishi $ */
2
 
3
#include "cm_crypt.h"
4
 
5
#include <unistd.h>
6
#include <stdio.h>
7
#include <stdlib.h>
8
#include <string.h>
9
 
6 nishi 10
#ifdef __linux__
11
#include <crypt.h>
12
#endif
13
 
7 nishi 14
const char* cm_crypt_methods[] = {"DES",    "MD5", "Blowfish", "", "", "SHA-256", "SHA-512",
15
#ifdef __NetBSD__
16
				  "Argon2",
17
#endif
18
				  NULL};
5 nishi 19
 
20
char* cm_crypt_spec(int num, const char* string, const char* salt) {
21
	char* r = NULL;
22
	if(num == C_DES) {
23
		r = crypt(string, salt);
24
	} else if(num == C_MD5 || num == C_SHA256 || num == C_SHA512) {
7 nishi 25
		char* buffer = malloc(3 + strlen(salt) + 1 + 1);
26
		buffer[3 + strlen(salt) + 1] = 0;
27
		sprintf(buffer, "$%d$%s$", num, salt);
5 nishi 28
 
29
		r = crypt(string, buffer);
30
 
31
		free(buffer);
32
	} else if(num == C_BLOWFISH) {
7 nishi 33
		char* buffer = malloc(4 + 3 + strlen(salt) + 1 + 1);
34
		buffer[4 + 3 + strlen(salt) + 1] = 0;
35
		sprintf(buffer, "$%da$08$%s$", num, salt);
5 nishi 36
 
37
		r = crypt(string, buffer);
38
 
39
		free(buffer);
8 nishi 40
	}
41
#ifdef __NetBSD__
42
	else if(num == C_ARGON2) {
7 nishi 43
		if(strlen(salt) != 16) return NULL;
44
		char* buffer = malloc(1 + 8 + 1 + 4 + 1 + 16 + 1 + 1 + 7);
45
		buffer[1 + 8 + 1 + 4 + 1 + 16 + 1 + 7] = 0;
46
		sprintf(buffer, "$argon2id$v=19$m=4096$%s$", salt);
47
 
48
		r = crypt(string, buffer);
49
 
50
		free(buffer);
5 nishi 51
	}
8 nishi 52
#endif
5 nishi 53
	if(r == NULL || strcmp(r, "*0") == 0 || strcmp(r, ":") == 0) r = NULL;
54
	return r;
55
}
56
 
57
int cm_crypt_try(int num) {
58
	printf("Trying %s... ", cm_crypt_methods[num]);
59
	fflush(stdout);
60
 
61
	if(cm_crypt_spec(num, "random", "randomrandomrandomrandom") != NULL) {
62
		printf("works\n");
63
		return 1;
64
	}
7 nishi 65
 
66
#ifdef __NetBSD__
67
	if(cm_crypt_spec(num, "random", "abcdabcdabcdabcd") != NULL) {
68
		printf("works\n");
69
		return 1;
70
	}
71
#endif
72
 
73
	printf("does not work\n");
74
 
75
	return 0;
5 nishi 76
}
77
 
78
int cm_chosen_crypt;
79
 
80
int cm_crypt_init(void) {
81
	int i;
82
	int last = -1;
83
	for(i = C_START + 1; i < C_END; i++) {
84
		if(strlen(cm_crypt_methods[i]) != 0) {
85
			if(cm_crypt_try(i)) {
86
				last = i;
87
			}
88
		}
89
	}
90
	cm_chosen_crypt = last;
91
	return last;
92
}
93
 
94
char* cm_crypt(const char* string) {
95
	char salt[65];
96
	salt[64] = 0;
97
	int i;
98
	FILE* f = fopen("/dev/urandom", "rb");
99
	unsigned char c;
100
	const char usable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
101
	for(i = 0; i < 64; i++) {
102
		fread(&c, 1, 1, f);
103
		salt[i] = c % strlen(usable);
104
	}
9 nishi 105
#ifdef __NetBSD__
106
	if(cm_chosen_crypt == C_ARGON2) {
107
		salt[16] = 0;
108
	}
109
#endif
5 nishi 110
	fclose(f);
111
	return cm_crypt_spec(cm_chosen_crypt, string, salt);
112
}