1 /*
2    3APA3A simpliest proxy server
3    (c) 2002-2016 by Vladimir Dubrovin <3proxy@3proxy.ru>
4 
5    please read License Agreement
6 
7 */
8 #include "libs/md5.h"
9 #include "libs/md4.h"
10 #include <string.h>
11 
12 #define MD5_SIZE 16
13 
14 #ifdef _WIN32
15 #pragma warning (disable : 4996)
16 #endif
17 
18 
19 void tohex(unsigned char *in, unsigned char *out, int len);
20 
21 static unsigned char itoa64[] =
22         "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
23 
24 void
_crypt_to64(unsigned char * s,unsigned long v,int n)25 _crypt_to64(unsigned char *s, unsigned long v, int n)
26 {
27         while (--n >= 0) {
28                 *s++ = itoa64[v&0x3f];
29                 v >>= 6;
30         }
31 }
32 
33 
ntpwdhash(unsigned char * szHash,const unsigned char * szPassword,int ctohex)34 unsigned char * ntpwdhash (unsigned char *szHash, const unsigned char *szPassword, int ctohex)
35 {
36 	unsigned char szUnicodePass[513];
37 	unsigned int nPasswordLen;
38 	MD4_CTX ctx;
39 	unsigned int i;
40 
41 	/*
42 	 *	NT passwords are unicode.  Convert plain text password
43 	 *	to unicode by inserting a zero every other byte
44 	 */
45 	nPasswordLen = (int)strlen((char *)szPassword);
46 	if(nPasswordLen > 255)nPasswordLen = 255;
47 	for (i = 0; i < nPasswordLen; i++) {
48 		szUnicodePass[i << 1] = szPassword[i];
49 		szUnicodePass[(i << 1) + 1] = 0;
50 	}
51 
52 	/* Encrypt Unicode password to a 16-byte MD4 hash */
53 	MD4Init(&ctx);
54 	MD4Update(&ctx, szUnicodePass, (nPasswordLen<<1));
55 	MD4Final(szUnicodePass, &ctx);
56 	if (ctohex){
57 		tohex(szUnicodePass, szHash, 16);
58 	}
59 	else memcpy(szHash, szUnicodePass, 16);
60 	return szHash;
61 }
62 
63 
mycrypt(const unsigned char * pw,const unsigned char * salt,unsigned char * passwd)64 unsigned char * mycrypt(const unsigned char *pw, const unsigned char *salt, unsigned char *passwd){
65 
66  const unsigned char *ep;
67  if(salt[0] == '$' && salt[1] == '1' && salt[2] == '$' && (ep = (unsigned char *)strchr((char *)salt+3, '$'))) {
68 	static unsigned char	*magic = (unsigned char *)"$1$";
69 	unsigned char  *p;
70 	const unsigned char *sp;
71 	unsigned char	final[MD5_SIZE];
72 	int sl,pl,i;
73 	MD5_CTX	ctx,ctx1;
74 	unsigned long l;
75 
76 	/* Refine the Salt first */
77 	sp = salt +3;
78 
79 	/* get the length of the true salt */
80 	sl = (int)(ep - sp);
81 
82 	MD5Init(&ctx);
83 
84 	/* The password first, since that is what is most unknown */
85 	MD5Update(&ctx,pw,strlen((char *)pw));
86 
87 	/* Then our magic string */
88 	MD5Update(&ctx,magic,strlen((char *)magic));
89 
90 	/* Then the raw salt */
91 	MD5Update(&ctx,sp,sl);
92 
93 	/* Then just as many unsigned characters of the MD5(pw,salt,pw) */
94 	MD5Init(&ctx1);
95 	MD5Update(&ctx1,pw,strlen((char *)pw));
96 	MD5Update(&ctx1,sp,sl);
97 	MD5Update(&ctx1,pw,strlen((char *)pw));
98 	MD5Final(final,&ctx1);
99 	for(pl = (int)strlen((char *)pw); pl > 0; pl -= MD5_SIZE)
100 		MD5Update(&ctx,final,pl>MD5_SIZE ? MD5_SIZE : pl);
101 
102 	/* Don't leave anything around in vm they could use. */
103 	memset(final,0,sizeof final);
104 
105 	/* Then something really weird... */
106 	for (i = (int)strlen((char *)pw); i ; i >>= 1)
107 		if(i&1)
108 		    MD5Update(&ctx, final, 1);
109 		else
110 		    MD5Update(&ctx, pw, 1);
111 
112 	/* Now make the output string */
113 	strcpy((char *)passwd,(char *)magic);
114 	strncat((char *)passwd,(char *)sp,sl);
115 	strcat((char *)passwd,"$");
116 
117 	MD5Final(final,&ctx);
118 
119 	/*
120 	 * and now, just to make sure things don't run too fast
121 	 * On a 60 Mhz Pentium this takes 34 msec, so you would
122 	 * need 30 seconds to build a 1000 entry dictionary...
123 	 */
124 	for(i=0;i<1000;i++) {
125 		MD5Init(&ctx1);
126 		if(i & 1)
127 			MD5Update(&ctx1,pw,strlen((char *)pw));
128 		else
129 			MD5Update(&ctx1,final,MD5_SIZE);
130 
131 		if(i % 3)
132 			MD5Update(&ctx1,sp,sl);
133 
134 		if(i % 7)
135 			MD5Update(&ctx1,pw,strlen((char *)pw));
136 
137 		if(i & 1)
138 			MD5Update(&ctx1,final,MD5_SIZE);
139 		else
140 			MD5Update(&ctx1,pw,strlen((char *)pw));
141 		MD5Final(final,&ctx1);
142 	}
143 
144 	p = passwd + strlen((char *)passwd);
145 
146 	l = (final[ 0]<<16) | (final[ 6]<<8) | final[12];
147 	_crypt_to64(p,l,4); p += 4;
148 	l = (final[ 1]<<16) | (final[ 7]<<8) | final[13];
149 	_crypt_to64(p,l,4); p += 4;
150 	l = (final[ 2]<<16) | (final[ 8]<<8) | final[14];
151 	_crypt_to64(p,l,4); p += 4;
152 	l = (final[ 3]<<16) | (final[ 9]<<8) | final[15];
153 	_crypt_to64(p,l,4); p += 4;
154 	l = (final[ 4]<<16) | (final[10]<<8) | final[ 5];
155 	_crypt_to64(p,l,4); p += 4;
156 	l =                    final[11]                ;
157 	_crypt_to64(p,l,2); p += 2;
158 	*p = '\0';
159 
160 	/* Don't leave anything around in vm they could use. */
161 	memset(final,0,sizeof final);
162  }
163  else {
164 	*passwd = 0;
165  }
166  return passwd;
167 }
168 
169 #ifdef WITHMAIN
170 
171 #include <stdio.h>
main(int argc,char * argv[])172 int main(int argc, char* argv[]){
173 	unsigned char buf[1024];
174 	unsigned i;
175 	if(argc < 2 || argc > 3) {
176 		fprintf(stderr, "usage: \n"
177 			"\t%s <password>\n"
178 			"\t%s <salt> <password>\n"
179 			"Performs NT crypt if no salt specified, MD5 crypt with salt\n"
180 			"This software uses:\n"
181 			"  RSA Data Security, Inc. MD4 Message-Digest Algorithm\n"
182 			"  RSA Data Security, Inc. MD5 Message-Digest Algorithm\n",
183 			argv[0],
184 			argv[0]);
185 			return 1;
186 	}
187 	if(argc == 2) {
188 		printf("NT:%s\n", ntpwdhash(buf, (unsigned char *)argv[1], 1));
189 	}
190 	else {
191 		i = (int)strlen((char *)argv[1]);
192 		if (i > 64) argv[1][64] = 0;
193 		sprintf((char *)buf, "$1$%s$", argv[1]);
194 		printf("CR:%s\n", mycrypt((unsigned char *)argv[2], buf, buf+256));
195 	}
196 	return 0;
197 }
198 
199 #endif
200