1 /*
2  * Ostatnia aktualizacja:
3  *
4  * - $Id: auth.c,v 1.19 2002/11/25 18:20:49 mati Exp $
5  *
6  */
7 
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include "libtlen.h"
12 
13 static void shaHashBlock (j_SHA_CTX * ctx);
14 
15 void
shaInit(j_SHA_CTX * ctx)16 shaInit (j_SHA_CTX * ctx)
17 {
18 	int i;
19 
20 	ctx->lenW = 0;
21 	ctx->sizeHi = ctx->sizeLo = 0;
22 
23 	/* Initialize H with the magic constants (see FIPS180 for constants)
24 	 */
25 	ctx->H[0] = 0x67452301L;
26 	ctx->H[1] = 0xefcdab89L;
27 	ctx->H[2] = 0x98badcfeL;
28 	ctx->H[3] = 0x10325476L;
29 	ctx->H[4] = 0xc3d2e1f0L;
30 
31 	for (i = 0; i < 80; i++)
32 		ctx->W[i] = 0;
33 }
34 
35 
36 void
shaUpdate(j_SHA_CTX * ctx,unsigned char * dataIn,int len)37 shaUpdate (j_SHA_CTX * ctx, unsigned char *dataIn, int len)
38 {
39 	int i;
40 
41 	/* Read the data into W and process blocks as they get full
42 	 */
43 	for (i = 0; i < len; i++)
44 	{
45 		ctx->W[ctx->lenW / 4] <<= 8;
46 		ctx->W[ctx->lenW / 4] |= (unsigned long) dataIn[i];
47 		if ((++ctx->lenW) % 64 == 0)
48 		{
49 			shaHashBlock (ctx);
50 			ctx->lenW = 0;
51 		}
52 		ctx->sizeLo += 8;
53 		ctx->sizeHi += (ctx->sizeLo < 8);
54 	}
55 }
56 
57 
58 void
shaFinal(j_SHA_CTX * ctx,unsigned char hashout[20])59 shaFinal (j_SHA_CTX * ctx, unsigned char hashout[20])
60 {
61 	unsigned char pad0x80 = 0x80;
62 	unsigned char pad0x00 = 0x00;
63 	unsigned char padlen[8];
64 	int i;
65 
66 	/* Pad with a binary 1 (e.g. 0x80), then zeroes, then length
67 	 */
68 	padlen[0] = (unsigned char) ((ctx->sizeHi >> 24) & 255);
69 	padlen[1] = (unsigned char) ((ctx->sizeHi >> 16) & 255);
70 	padlen[2] = (unsigned char) ((ctx->sizeHi >> 8) & 255);
71 	padlen[3] = (unsigned char) ((ctx->sizeHi >> 0) & 255);
72 	padlen[4] = (unsigned char) ((ctx->sizeLo >> 24) & 255);
73 	padlen[5] = (unsigned char) ((ctx->sizeLo >> 16) & 255);
74 	padlen[6] = (unsigned char) ((ctx->sizeLo >> 8) & 255);
75 	padlen[7] = (unsigned char) ((ctx->sizeLo >> 0) & 255);
76 	shaUpdate (ctx, &pad0x80, 1);
77 	while (ctx->lenW != 56)
78 		shaUpdate (ctx, &pad0x00, 1);
79 	shaUpdate (ctx, padlen, 8);
80 
81 	/* Output hash
82 	 */
83 	for (i = 0; i < 20; i++)
84 	{
85 		hashout[i] = (unsigned char) (ctx->H[i / 4] >> 24);
86 		ctx->H[i / 4] <<= 8;
87 	}
88 
89 	/*
90 	 *  Re-initialize the context (also zeroizes contents)
91 	 */
92 	shaInit (ctx);
93 }
94 
95 
96 void
shaBlock(unsigned char * dataIn,int len,unsigned char hashout[20])97 shaBlock (unsigned char *dataIn, int len, unsigned char hashout[20])
98 {
99 	j_SHA_CTX ctx;
100 
101 	shaInit (&ctx);
102 	shaUpdate (&ctx, dataIn, len);
103 	shaFinal (&ctx, hashout);
104 }
105 
106 
107 #define SHA_ROTL(X,n) ((((X) << (n)) | ((X) >> (32-(n)))) & 0xffffffffL)
108 
109 static void
shaHashBlock(j_SHA_CTX * ctx)110 shaHashBlock (j_SHA_CTX * ctx)
111 {
112 	int t;
113 	unsigned long A, B, C, D, E, TEMP;
114 
115 	for (t = 16; t <= 79; t++)
116 		ctx->W[t] =
117 			SHA_ROTL (ctx->W[t - 3] ^ ctx->W[t - 8] ^ ctx->
118 				  W[t - 14] ^ ctx->W[t - 16], 1);
119 
120 	A = ctx->H[0];
121 	B = ctx->H[1];
122 	C = ctx->H[2];
123 	D = ctx->H[3];
124 	E = ctx->H[4];
125 
126 	for (t = 0; t <= 19; t++)
127 	{
128 		TEMP = (SHA_ROTL (A, 5) + (((C ^ D) & B) ^ D) + E +
129 			ctx->W[t] + 0x5a827999L) & 0xffffffffL;
130 		E = D;
131 		D = C;
132 		C = SHA_ROTL (B, 30);
133 		B = A;
134 		A = TEMP;
135 	}
136 	for (t = 20; t <= 39; t++)
137 	{
138 		TEMP = (SHA_ROTL (A, 5) + (B ^ C ^ D) + E + ctx->W[t] +
139 			0x6ed9eba1L) & 0xffffffffL;
140 		E = D;
141 		D = C;
142 		C = SHA_ROTL (B, 30);
143 		B = A;
144 		A = TEMP;
145 	}
146 	for (t = 40; t <= 59; t++)
147 	{
148 		TEMP = (SHA_ROTL (A, 5) + ((B & C) | (D & (B | C))) + E +
149 			ctx->W[t] + 0x8f1bbcdcL) & 0xffffffffL;
150 		E = D;
151 		D = C;
152 		C = SHA_ROTL (B, 30);
153 		B = A;
154 		A = TEMP;
155 	}
156 	for (t = 60; t <= 79; t++)
157 	{
158 		TEMP = (SHA_ROTL (A, 5) + (B ^ C ^ D) + E + ctx->W[t] +
159 			0xca62c1d6L) & 0xffffffffL;
160 		E = D;
161 		D = C;
162 		C = SHA_ROTL (B, 30);
163 		B = A;
164 		A = TEMP;
165 	}
166 
167 	ctx->H[0] += A;
168 	ctx->H[1] += B;
169 	ctx->H[2] += C;
170 	ctx->H[3] += D;
171 	ctx->H[4] += E;
172 }
173 
174 /*----------------------------------------------------------------------------
175  *
176  * This code added by Thomas "temas" Muldowney for Jabber compatability
177  *
178  *---------------------------------------------------------------------------*/
179 char *
shahash(char * str)180 shahash (char *str)
181 {
182 	static char final[41];
183 	char *pos;
184 	unsigned char hashval[20];
185 	int x;
186 
187 	if (!str || strlen (str) == 0)
188 		return NULL;
189 
190 	shaBlock ((unsigned char *) str, strlen (str), hashval);
191 
192 	pos = final;
193 	for (x = 0; x < 20; x++)
194 	{
195 		snprintf (pos, 3, "%02x", hashval[x]);
196 		pos += 2;
197 	}
198 	return (char *) final;
199 }
200 
201 void
shahash_r(const char * str,char hashbuf[41])202 shahash_r (const char *str, char hashbuf[41])
203 {
204 	int x;
205 	char *pos;
206 	unsigned char hashval[20];
207 
208 	if (!str || strlen (str) == 0)
209 		return;
210 
211 	shaBlock ((unsigned char *) str, strlen (str), hashval);
212 
213 	pos = hashbuf;
214 	for (x = 0; x < 20; x++)
215 	{
216 		snprintf (pos, 3, "%02x", hashval[x]);
217 		pos += 2;
218 	}
219 
220 	return;
221 }
222 
223 /*********************************************/
224 // Ten kod dodany przeze mnie i Piotra Paw�owa
225 
226 void
calc_passcode(const char * pass,char * code)227 calc_passcode (const char *pass, char *code)
228 {
229 	int magic1 = 0x50305735, magic2 = 0x12345671, sum = 7;
230 	char z;
231 	while ((z = *pass++) != 0)
232 	{
233 		if (z == ' ')
234 			continue;
235 		if (z == '\t')
236 			continue;
237 		magic1 ^= (((magic1 & 0x3f) + sum) * z) + (magic1 << 8);
238 		magic2 += (magic2 << 8) ^ magic1;
239 		sum += z;
240 	}
241 	magic1 &= 0x7fffffff;
242 	magic2 &= 0x7fffffff;
243 	sprintf (code, "%08x%08x", magic1, magic2);
244 }
245 
246 /*
247  * tlen_hash()
248  *
249  * Generuje hash potrzebny do zalogowania si�
250  *
251  * - pass - has�o
252  * - id - identyfikator sesji
253  *
254  * Funkcja wewn�trzna na potrzeby tlen_authorize
255  *
256  */
257 
tlen_hash(const char * pass,const char * id)258 char *tlen_hash (const char *pass, const char *id)
259 {
260 	char passcode[17];
261 	char dohasha[25];
262 	char *hash;
263 	hash = (char *) malloc (41);
264 	calc_passcode (pass, passcode);
265 	strcpy (dohasha, id);
266 	strcat (dohasha, passcode);
267         dohasha[24]=0;
268 	shahash_r (dohasha, hash);
269 	return (char *) hash;
270 }
271 
272 /*
273  * tlen_getid()
274  *
275  * Wysy�a pro�b� o ID do serwera
276  *
277  * - sesja - nasza sesja
278  *
279  * Wywo�ywane zaraz po po��czeniu
280  *
281  */
282 
tlen_getid(struct tlen_session * sesja)283 int tlen_getid (struct tlen_session *sesja)
284 {
285 	tlen_socket_write_string (sesja, "<s v='2'>");
286 	return 1;
287 }
288 
289 /*
290  * tlen_authorize()
291  *
292  * Wysy�a zapytanie loguj�ce do serwera
293  *
294  * - sesja - nasza sesja
295  *
296  * Wywo�ywane po otrzymaniu ID
297  *
298  */
299 
tlen_authorize(struct tlen_session * sesja)300 int tlen_authorize (struct tlen_session *sesja)
301 {
302 	char *query;
303 	char *hash;
304 
305 	tlen_debug ("Username: %s\nHaslo: <hidden>\nID: %s\n", sesja->username, sesja->sid);
306 
307 	if (!(query = (char *)malloc (strlen("<iq type='set' id=''><query xmlns='jabber:iq:auth'><username></username><digest></digest><resource>t</resource></query></iq>") + strlen (sesja->username) + 40 + 8 + 1)))
308 	{
309 		perror ("malloc");
310 		sesja->error = TLEN_ERROR_MALLOC;
311 	}
312 
313 	hash = tlen_hash (sesja->password, sesja->sid);
314 	sprintf (query,"<iq type='set' id='%s'><query xmlns='jabber:iq:auth'><username>%s</username><digest>%s</digest><resource>t</resource></query></iq>",sesja->sid, sesja->username, hash);
315 	tlen_socket_write_string (sesja, query);
316 	free (query);
317         free (hash);
318 	return 1;
319 }
320