diff --git a/include/libgadu.h.in b/include/libgadu.h.in index 4584467f..14f13d00 100644 --- a/include/libgadu.h.in +++ b/include/libgadu.h.in @@ -176,10 +176,10 @@ struct gg_session { uint32_t external_addr; /* adres zewnetrzny klienta */ uint16_t external_port; /* port zewnetrzny klienta */ - + uin_t uin; /* numerek klienta */ char *password; /* i jego hasło. zwalniane automagicznie */ - + int initial_status; /* początkowy stan klienta */ int status; /* aktualny stan klienta */ @@ -213,13 +213,11 @@ struct gg_session { int userlist_blocks; /* na ile kawałków podzielono listę kontaktów */ struct gg_image_queue *images; /* aktualnie wczytywane obrazki */ - - int hash_type; /* rodzaj hasha hasła używanego przy logowaniu */ }; /* * struct gg_http - * + * * ogólna struktura opisująca stan wszystkich operacji HTTP. tworzona * przez gg_http_connect(), zwalniana przez gg_http_free(). */ @@ -255,7 +253,7 @@ struct gg_http { /* * struct gg_file_info - * + * * odpowiednik windowsowej struktury WIN32_FIND_DATA niezbędnej przy * wysyłaniu plików. */ @@ -274,7 +272,7 @@ struct gg_file_info { /* * struct gg_dcc - * + * * struktura opisująca nasłuchujące gniazdo połączeń między klientami. * tworzona przez gg_dcc_socket_create(), zwalniana przez gg_dcc_free(). */ @@ -324,7 +322,7 @@ enum gg_session_t { GG_SESSION_UNREGISTER, /* usuwanie konta */ GG_SESSION_USERLIST_REMOVE, /* usuwanie userlisty */ GG_SESSION_TOKEN, /* pobieranie tokenu */ - + GG_SESSION_USER0 = 256, /* zdefiniowana dla użytkownika */ GG_SESSION_USER1, /* j.w. */ GG_SESSION_USER2, /* j.w. */ @@ -427,10 +425,9 @@ struct gg_login_params { int tls; /* czy łączymy po TLS? */ int image_size; /* maksymalny rozmiar obrazka w KiB */ int era_omnix; /* czy udawać klienta era omnix? */ - int hash_type; /* rodzaj hasha */ - char dummy[5 * sizeof(int)]; /* miejsce na kolejnych 5 zmiennych, - * żeby z dodaniem parametru nie + char dummy[6 * sizeof(int)]; /* miejsce na kolejnych 6 zmiennych, + * żeby z dodaniem parametru nie * zmieniał się rozmiar struktury */ }; @@ -586,11 +583,11 @@ struct gg_event { enum gg_failure_t failure; /* błąd połączenia -- GG_EVENT_FAILURE */ struct gg_dcc *dcc_new; /* nowe połączenie bezpośrednie -- GG_EVENT_DCC_NEW */ - + int dcc_error; /* błąd połączenia bezpośredniego -- GG_EVENT_DCC_ERROR */ gg_pubdir50_t pubdir50; /* wynik operacji związanej z katalogiem publicznym -- GG_EVENT_PUBDIR50_* */ - + struct { /* @msg odebrano wiadomość -- GG_EVENT_MSG */ uin_t sender; /* numer nadawcy */ int msgclass; /* klasa wiadomości */ @@ -599,16 +596,16 @@ struct gg_event { int recipients_count; /* ilość odbiorców konferencji */ uin_t *recipients; /* odbiorcy konferencji */ - + int formats_length; /* długość informacji o formatowaniu tekstu */ void *formats; /* informacje o formatowaniu tekstu */ } msg; - + struct { /* @notify_descr informacje o liście kontaktów z opisami stanu -- GG_EVENT_NOTIFY_DESCR */ struct gg_notify_reply *notify; /* informacje o liście kontaktów */ char *descr; /* opis stanu */ } notify_descr; - + struct { /* @status zmiana stanu -- GG_EVENT_STATUS */ uin_t uin; /* numer */ uint32_t status; /* nowy stan */ @@ -636,7 +633,7 @@ struct gg_event { char *descr; /* opis stanu */ time_t time; /* czas powrotu */ } *notify60; - + struct { /* @ack potwierdzenie wiadomości -- GG_EVENT_ACK */ uin_t recipient; /* numer odbiorcy */ int status; /* stan doręczenia wiadomości */ @@ -843,7 +840,7 @@ struct gg_http *gg_change_passwd4(uin_t uin, const char *email, const char *pass /* * struct gg_change_info_request - * + * * opis żądania zmiany informacji w katalogu publicznym. */ struct gg_change_info_request { @@ -918,7 +915,7 @@ extern int gg_debug_level; /* poziom debugowania. mapa bitowa sta /* * można podać wskaźnik do funkcji obsługującej wywołania gg_debug(). - * nieoficjalne, nieudokumentowane, może się zmienić. jeśli ktoś jest + * nieoficjalne, nieudokumentowane, może się zmienić. jeśli ktoś jest * zainteresowany, niech da znać na ekg-devel. */ extern void (*gg_debug_handler)(int level, const char *format, va_list ap); @@ -956,11 +953,11 @@ extern char *gg_proxy_password; /* okre extern int gg_proxy_http_only; /* włącza obsługę proxy wyłącznie dla usług HTTP */ -/* +/* * adres, z którego ślemy pakiety (np łączymy się z serwerem) * używany przy gg_connect() */ -extern unsigned long gg_local_ip; +extern unsigned long gg_local_ip; /* * ------------------------------------------------------------------------- * poniżej znajdują się wewnętrzne sprawy biblioteki. zwykły klient nie @@ -972,6 +969,7 @@ extern unsigned long gg_local_ip; #ifdef GG_CONFIG_HAVE_PTHREAD int gg_resolve_pthread(int *fd, void **resolver, const char *hostname); +void gg_resolve_pthread_cleanup(void *resolver, int kill); #endif #ifdef _WIN32 @@ -1003,7 +1001,6 @@ int gg_write(struct gg_session *sess, const char *buf, int length); void *gg_recv_packet(struct gg_session *sess); int gg_send_packet(struct gg_session *sess, int type, ...); unsigned int gg_login_hash(const unsigned char *password, unsigned int seed); -void gg_login_hash_sha1(const char *password, uint32_t seed, uint8_t *result); uint32_t gg_fix32(uint32_t x); uint16_t gg_fix16(uint16_t x); #define fix16 gg_fix16 @@ -1046,7 +1043,7 @@ struct gg_header { struct gg_welcome { uint32_t key; /* klucz szyfrowania hasła */ } GG_PACKED; - + #define GG_LOGIN 0x000c struct gg_login { @@ -1087,26 +1084,6 @@ struct gg_login60 { uint8_t dunno2; /* 0xbe */ } GG_PACKED; -#define GG_LOGIN70 0x19 - -#define GG_LOGIN_HASH_GG32 0x01 -#define GG_LOGIN_HASH_SHA1 0x02 - -struct gg_login70 { - uint32_t uin; /* mój numerek */ - uint8_t hash_type; /* rodzaj hashowania hasła */ - uint8_t hash[64]; /* hash hasła dopełniony zerami */ - uint32_t status; /* status na dzień dobry */ - uint32_t version; /* moja wersja klienta */ - uint8_t dunno1; /* 0x00 */ - uint32_t local_ip; /* mój adres ip */ - uint16_t local_port; /* port, na którym słucham */ - uint32_t external_ip; /* zewnętrzny adres ip (???) */ - uint16_t external_port; /* zewnętrzny port (???) */ - uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */ - uint8_t dunno2; /* 0xbe */ -} GG_PACKED; - #define GG_LOGIN_OK 0x0003 #define GG_LOGIN_FAILED 0x0009 @@ -1183,7 +1160,7 @@ struct gg_new_status { #define GG_NOTIFY_LAST 0x0010 #define GG_NOTIFY 0x0010 - + struct gg_notify { uint32_t uin; /* numerek danej osoby */ uint8_t dunno1; /* rodzaj wpisu w liście */ @@ -1194,9 +1171,9 @@ struct gg_notify { #define GG_USER_BLOCKED 0x04 /* zablokowany użytkownik */ #define GG_LIST_EMPTY 0x0012 - + #define GG_NOTIFY_REPLY 0x000c /* tak, to samo co GG_LOGIN */ - + struct gg_notify_reply { uint32_t uin; /* numerek */ uint32_t status; /* status danej osoby */ @@ -1207,7 +1184,7 @@ struct gg_notify_reply { } GG_PACKED; #define GG_NOTIFY_REPLY60 0x0011 - + struct gg_notify_reply60 { uint32_t uin; /* numerek plus flagi w MSB */ uint8_t status; /* status danej osoby */ @@ -1219,7 +1196,7 @@ struct gg_notify_reply60 { } GG_PACKED; #define GG_STATUS60 0x000f - + struct gg_status60 { uint32_t uin; /* numerek plus flagi w MSB */ uint8_t status; /* status danej osoby */ @@ -1232,7 +1209,7 @@ struct gg_status60 { #define GG_ADD_NOTIFY 0x000d #define GG_REMOVE_NOTIFY 0x000e - + struct gg_add_remove { uint32_t uin; /* numerek */ uint8_t dunno1; /* bitmapa */ @@ -1244,7 +1221,7 @@ struct gg_status { uint32_t uin; /* numerek */ uint32_t status; /* nowy stan */ } GG_PACKED; - + #define GG_SEND_MSG 0x000b #define GG_CLASS_QUEUED 0x0001 @@ -1264,13 +1241,13 @@ struct gg_send_msg { } GG_PACKED; struct gg_msg_richtext { - uint8_t flag; - uint16_t length; + uint8_t flag; + uint16_t length; } GG_PACKED; struct gg_msg_richtext_format { uint16_t position; - uint8_t font; + uint8_t font; } GG_PACKED; struct gg_msg_richtext_image { @@ -1285,7 +1262,7 @@ struct gg_msg_richtext_image { #define GG_FONT_COLOR 0x08 #define GG_FONT_IMAGE 0x80 -struct gg_msg_richtext_color { +struct gg_msg_richtext_color { uint8_t red; uint8_t green; uint8_t blue; @@ -1317,7 +1294,7 @@ struct gg_msg_image_reply { #define GG_ACK_QUEUED 0x0003 #define GG_ACK_MBOXFULL 0x0004 #define GG_ACK_NOT_DELIVERED 0x0006 - + struct gg_send_msg_ack { uint32_t status; uint32_t recipient; @@ -1325,7 +1302,7 @@ struct gg_send_msg_ack { } GG_PACKED; #define GG_RECV_MSG 0x000a - + struct gg_recv_msg { uint32_t sender; uint32_t seq; @@ -1334,7 +1311,7 @@ struct gg_recv_msg { } GG_PACKED; #define GG_PING 0x0008 - + #define GG_PONG 0x0007 #define GG_DISCONNECTING 0x000b diff --git a/src/Makefile.am b/src/Makefile.am index 33785e1f..95c86903 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,4 @@ lib_LTLIBRARIES = libgadu.la -libgadu_la_SOURCES = common.c dcc.c events.c http.c obsolete.c pubdir.c pubdir50.c libgadu.c sha1.c +libgadu_la_SOURCES = common.c dcc.c events.c http.c obsolete.c pubdir.c pubdir50.c libgadu.c libgadu_la_CFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include libgadu_la_LDFLAGS = -version-number 3:7 diff --git a/src/events.c b/src/events.c index 68458f44..61913517 100644 --- a/src/events.c +++ b/src/events.c @@ -606,10 +606,13 @@ static int gg_watch_fd_connected(struct gg_session *sess, struct gg_event *e) e->event.notify60[i].descr[descr_len] = 0; /* XXX czas */ + + length -= sizeof(struct gg_notify_reply60) + descr_len + 1; + n = (void*) ((char*) n + sizeof(struct gg_notify_reply60) + descr_len + 1); + } else { + length = 0; } - length -= sizeof(struct gg_notify_reply60) + descr_len + 1; - n = (void*) ((char*) n + sizeof(struct gg_notify_reply60) + descr_len + 1); } else { length -= sizeof(struct gg_notify_reply60); n = (void*) ((char*) n + sizeof(struct gg_notify_reply60)); @@ -832,8 +835,7 @@ struct gg_event *gg_watch_fd(struct gg_session *sess) sess->pid = -1; #else if (sess->resolver) { - pthread_cancel(*((pthread_t*) sess->resolver)); - free(sess->resolver); + gg_resolve_pthread_cleanup(sess->resolver, 0); sess->resolver = NULL; } #endif @@ -1334,7 +1336,8 @@ struct gg_event *gg_watch_fd(struct gg_session *sess) { struct gg_header *h; struct gg_welcome *w; - struct gg_login70 l; + struct gg_login60 l; + unsigned int hash; unsigned char *password = (unsigned char*) sess->password; int ret; @@ -1396,34 +1399,9 @@ struct gg_event *gg_watch_fd(struct gg_session *sess) w = (struct gg_welcome*) ((char*) h + sizeof(struct gg_header)); w->key = gg_fix32(w->key); - l.hash_type = sess->hash_type; - - switch (sess->hash_type) { - case GG_LOGIN_HASH_GG32: - { - unsigned int hash; - - hash = gg_login_hash(password, w->key); - gg_debug_session(sess, GG_DEBUG_DUMP, "// gg_watch_fd() challenge %.4x --> GG32 hash %.8x\n", w->key, hash); - memcpy(l.hash, &hash, sizeof(hash)); - - break; - } - - case GG_LOGIN_HASH_SHA1: - { - char tmp[41]; - int i; - - gg_login_hash_sha1((char*) password, w->key, l.hash); - for (i = 0; i < 40; i += 2) - snprintf(tmp + i, sizeof(tmp) - i, "%02x", l.hash[i / 2]); - - gg_debug_session(sess, GG_DEBUG_DUMP, "// gg_watch_fd() challenge %.4x --> SHA1 hash: %s\n", w->key, tmp); + hash = gg_login_hash(password, w->key); - break; - } - } + gg_debug_session(sess, GG_DEBUG_DUMP, "// gg_watch_fd() challenge %.4x --> hash %.8x\n", w->key, hash); free(h); @@ -1453,18 +1431,19 @@ struct gg_event *gg_watch_fd(struct gg_session *sess) l.local_ip = gg_dcc_ip; l.uin = gg_fix32(sess->uin); + l.hash = gg_fix32(hash); l.status = gg_fix32(sess->initial_status ? sess->initial_status : GG_STATUS_AVAIL); l.version = gg_fix32(sess->protocol_version); l.local_port = gg_fix16(gg_dcc_port); l.image_size = sess->image_size; if (sess->external_addr && sess->external_port > 1023) { - l.local_ip = sess->external_addr; - l.local_port = gg_fix16(sess->external_port); + l.external_ip = sess->external_addr; + l.external_port = gg_fix16(sess->external_port); } - gg_debug_session(sess, GG_DEBUG_TRAFFIC, "// gg_watch_fd() sending GG_LOGIN70 packet\n"); - ret = gg_send_packet(sess, GG_LOGIN70, &l, sizeof(l), sess->initial_descr, (sess->initial_descr) ? strlen(sess->initial_descr) : 0, NULL); + gg_debug_session(sess, GG_DEBUG_TRAFFIC, "// gg_watch_fd() sending GG_LOGIN60 packet\n"); + ret = gg_send_packet(sess, GG_LOGIN60, &l, sizeof(l), sess->initial_descr, (sess->initial_descr) ? strlen(sess->initial_descr) : 0, NULL); free(sess->initial_descr); sess->initial_descr = NULL; diff --git a/src/http.c b/src/http.c index ae8bb798..1059e8e0 100644 --- a/src/http.c +++ b/src/http.c @@ -33,6 +33,7 @@ #ifdef GG_CONFIG_HAVE_PTHREAD # include #endif +#include #include #include #include @@ -200,8 +201,7 @@ int gg_http_watch_fd(struct gg_http *h) waitpid(h->pid, NULL, 0); #else if (h->resolver) { - pthread_cancel(*((pthread_t *) h->resolver)); - free(h->resolver); + gg_resolve_pthread_cleanup(h->resolver, 0); h->resolver = NULL; } #endif @@ -461,9 +461,23 @@ void gg_http_stop(struct gg_http *h) if (h->state == GG_STATE_ERROR || h->state == GG_STATE_DONE) return; - if (h->fd != -1) + if (h->fd != -1) { close(h->fd); - h->fd = -1; + h->fd = -1; + } + +#ifdef GG_CONFIG_HAVE_PTHREAD + if (h->resolver) { + gg_resolve_pthread_cleanup(h->resolver, 0); + h->resolver = NULL; + } +#else + if (h->pid != -1) { + kill(h->pid, SIGKILL); + waitpid(h->pid, NULL, 0); + h->pid = -1; + } +#endif } /* diff --git a/src/libgadu.c b/src/libgadu.c index b9319170..f88aa1a5 100644 --- a/src/libgadu.c +++ b/src/libgadu.c @@ -238,10 +238,45 @@ int gg_resolve(int *fd, int *pid, const char *hostname) #ifdef GG_CONFIG_HAVE_PTHREAD struct gg_resolve_pthread_data { + pthread_t thread; char *hostname; - int fd; + int rfd; + int wfd; }; +/* + * gg_resolve_pthread_cleanup() // funkcja wewnętrzna + * + * sprząta po wątku resolvera. + * + * - arg - wskaźnik na strukturę gg_resolve_pthread_data, + * - kill - czy zabić wątek resolvera i posprzątać po nim? + */ +void gg_resolve_pthread_cleanup(void *arg, int kill) +{ + struct gg_resolve_pthread_data *data = arg; + + if (kill) { + pthread_cancel(data->thread); + pthread_join(data->thread, NULL); + } + + free(data->hostname); + data->hostname = NULL; + + if (data->wfd != -1) { + close(data->wfd); + data->wfd = -1; + } + + free(data); +} + +/* + * gg_resolve_pthread_thread() // funkcja wewnętrzna + * + * wątek resolvera. + */ static void *gg_resolve_pthread_thread(void *arg) { struct gg_resolve_pthread_data *d = arg; @@ -260,13 +295,7 @@ static void *gg_resolve_pthread_thread(void *arg) } } - write(d->fd, &a, sizeof(a)); - close(d->fd); - - free(d->hostname); - d->hostname = NULL; - - free(d); + write(d->wfd, &a, sizeof(a)); pthread_exit(NULL); @@ -289,8 +318,7 @@ static void *gg_resolve_pthread_thread(void *arg) */ int gg_resolve_pthread(int *fd, void **resolver, const char *hostname) { - struct gg_resolve_pthread_data *d = NULL; - pthread_t *tmp; + struct gg_resolve_pthread_data *data = NULL; int pipes[2], new_errno; gg_debug(GG_DEBUG_FUNCTION, "** gg_resolve_pthread(%p, %p, \"%s\");\n", fd, resolver, hostname); @@ -301,58 +329,49 @@ int gg_resolve_pthread(int *fd, void **resolver, const char *hostname) return -1; } - if (!(tmp = malloc(sizeof(pthread_t)))) { - gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() out of memory for pthread id\n"); + if (!(data = malloc(sizeof(struct gg_resolve_pthread_data)))) { + gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() out of memory for resolver data\n"); return -1; } if (pipe(pipes) == -1) { gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() unable to create pipes (errno=%d, %s)\n", errno, strerror(errno)); - free(tmp); + free(data); return -1; } - if (!(d = malloc(sizeof(*d)))) { - gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() out of memory\n"); - new_errno = errno; - goto cleanup; - } - - d->hostname = NULL; - - if (!(d->hostname = strdup(hostname))) { + if (!(data->hostname = strdup(hostname))) { gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() out of memory\n"); new_errno = errno; goto cleanup; } - d->fd = pipes[1]; + data->rfd = pipes[0]; + data->wfd = pipes[1]; - if (pthread_create(tmp, NULL, gg_resolve_pthread_thread, d)) { + if (pthread_create(&data->thread, NULL, gg_resolve_pthread_thread, data)) { gg_debug(GG_DEBUG_MISC, "// gg_resolve_phread() unable to create thread\n"); new_errno = errno; goto cleanup; } - gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() %p\n", tmp); + gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() %p\n", data); - *resolver = tmp; + *resolver = data; *fd = pipes[0]; return 0; cleanup: - if (d) { - free(d->hostname); - free(d); + if (data) { + free(data->hostname); + free(data); } close(pipes[0]); close(pipes[1]); - free(tmp); - errno = new_errno; return -1; @@ -752,12 +771,6 @@ struct gg_session *gg_login(const struct gg_login_params *p) goto fail; } - if (p->hash_type < 0 || p->hash_type > GG_LOGIN_HASH_SHA1) { - gg_debug(GG_DEBUG_MISC, "// gg_login() invalid arguments. unknown hash type (%d)\n", p->hash_type); - errno = EFAULT; - goto fail; - } - sess->uin = p->uin; sess->state = GG_STATE_RESOLVING; sess->check = GG_CHECK_READ; @@ -831,11 +844,6 @@ struct gg_session *gg_login(const struct gg_login_params *p) port = GG_APPMSG_PORT; } - if (p->hash_type) - sess->hash_type = p->hash_type; - else - sess->hash_type = GG_LOGIN_HASH_SHA1; - if (!p->async) { struct in_addr a; @@ -960,13 +968,12 @@ void gg_free_session(struct gg_session *sess) #ifdef GG_CONFIG_HAVE_PTHREAD if (sess->resolver) { - pthread_cancel(*((pthread_t*) sess->resolver)); - free(sess->resolver); + gg_resolve_pthread_cleanup(sess->resolver, 1); sess->resolver = NULL; } #else if (sess->pid != -1) { - kill(sess->pid, SIGTERM); + kill(sess->pid, SIGKILL); waitpid(sess->pid, NULL, WNOHANG); } #endif @@ -1109,13 +1116,12 @@ void gg_logoff(struct gg_session *sess) #ifdef GG_CONFIG_HAVE_PTHREAD if (sess->resolver) { - pthread_cancel(*((pthread_t*) sess->resolver)); - free(sess->resolver); + gg_resolve_pthread_cleanup(sess->resolver, 1); sess->resolver = NULL; } #else if (sess->pid != -1) { - kill(sess->pid, SIGTERM); + kill(sess->pid, SIGKILL); waitpid(sess->pid, NULL, WNOHANG); sess->pid = -1; } diff --git a/src/sha1.c b/src/sha1.c deleted file mode 100644 index c014efe5..00000000 --- a/src/sha1.c +++ /dev/null @@ -1,223 +0,0 @@ -/* $Id$ */ - -/* - * (C) Copyright 2007 Wojtek Kaniewski - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License Version - * 2.1 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "libgadu.h" - -#ifdef GG_CONFIG_HAVE_OPENSSL - -#include - -#else - -/* -SHA-1 in C -By Steve Reid -100% Public Domain - -Modified by Wojtek Kaniewski for compatibility -with libgadu and OpenSSL API. - -Test Vectors (from FIPS PUB 180-1) -"abc" - A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D -"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 -A million repetitions of "a" - 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F -*/ - -/* #define LITTLE_ENDIAN * This should be #define'd if true. */ -/* #define SHA1HANDSOFF * Copies data before messing with it. */ - -#include - -typedef struct { - unsigned long state[5]; - unsigned long count[2]; - unsigned char buffer[64]; -} SHA_CTX; - -static void SHA1_Transform(unsigned long state[5], const unsigned char buffer[64]); -static void SHA1_Init(SHA_CTX* context); -static void SHA1_Update(SHA_CTX* context, const unsigned char* data, unsigned int len); -static void SHA1_Final(unsigned char digest[20], SHA_CTX* context); - -#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) - -/* blk0() and blk() perform the initial expand. */ -/* I got the idea of expanding during the round function from SSLeay */ -#ifndef WORDS_BIGENDIAN -#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ - |(rol(block->l[i],8)&0x00FF00FF)) -#else -#define blk0(i) block->l[i] -#endif -#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ - ^block->l[(i+2)&15]^block->l[i&15],1)) - -/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ -#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); -#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); -#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); -#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); -#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); - - -/* Hash a single 512-bit block. This is the core of the algorithm. */ - -static void SHA1_Transform(unsigned long state[5], const unsigned char buffer[64]) -{ -unsigned long a, b, c, d, e; -typedef union { - unsigned char c[64]; - unsigned long l[16]; -} CHAR64LONG16; -CHAR64LONG16* block; -static unsigned char workspace[64]; - block = (CHAR64LONG16*)workspace; - memcpy(block, buffer, 64); - /* Copy context->state[] to working vars */ - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - /* 4 rounds of 20 operations each. Loop unrolled. */ - R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); - R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); - R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); - R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); - R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); - R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); - R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); - R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); - R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); - R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); - R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); - R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); - R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); - R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); - R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); - R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); - R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); - R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); - R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); - R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); - /* Add the working vars back into context.state[] */ - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; - /* Wipe variables */ - a = b = c = d = e = 0; -} - - -/* SHA1_Init - Initialize new context */ - -static void SHA1_Init(SHA_CTX* context) -{ - /* SHA1 initialization constants */ - context->state[0] = 0x67452301; - context->state[1] = 0xEFCDAB89; - context->state[2] = 0x98BADCFE; - context->state[3] = 0x10325476; - context->state[4] = 0xC3D2E1F0; - context->count[0] = context->count[1] = 0; -} - - -/* Run your data through this. */ - -static void SHA1_Update(SHA_CTX* context, const unsigned char* data, unsigned int len) -{ -unsigned int i, j; - - j = (context->count[0] >> 3) & 63; - if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; - context->count[1] += (len >> 29); - if ((j + len) > 63) { - memcpy(&context->buffer[j], data, (i = 64-j)); - SHA1_Transform(context->state, context->buffer); - for ( ; i + 63 < len; i += 64) { - SHA1_Transform(context->state, &data[i]); - } - j = 0; - } - else i = 0; - memcpy(&context->buffer[j], &data[i], len - i); -} - - -/* Add padding and return the message digest. */ - -static void SHA1_Final(unsigned char digest[20], SHA_CTX* context) -{ -unsigned long i, j; -unsigned char finalcount[8]; - - for (i = 0; i < 8; i++) { - finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] - >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ - } - SHA1_Update(context, (unsigned char *)"\200", 1); - while ((context->count[0] & 504) != 448) { - SHA1_Update(context, (unsigned char *)"\0", 1); - } - SHA1_Update(context, finalcount, 8); /* Should cause a SHA1_Transform() */ - for (i = 0; i < 20; i++) { - digest[i] = (unsigned char) - ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); - } - /* Wipe variables */ - i = j = 0; - memset(context->buffer, 0, 64); - memset(context->state, 0, 20); - memset(context->count, 0, 8); - memset(&finalcount, 0, 8); -#ifdef SHA1HANDSOFF /* make SHA1_Transform overwrite it's own static vars */ - SHA1_Transform(context->state, context->buffer); -#endif -} - -#endif /* GG_CONFIG_HAVE_OPENSSL */ - -/** - * gg_login_hash_sha1() - * - * liczy hash z hasla i danego seeda, korzystajac z SHA1 - * - * - password - haslo do hashowania - * - seed - wartosc podana przez serwer - * - result - przynajmniej 20 znakowy bufor ktory otrzyma hash - */ -void gg_login_hash_sha1(const char *password, uint32_t seed, uint8_t *result) -{ - SHA_CTX ctx; - - SHA1_Init(&ctx); - SHA1_Update(&ctx, (const unsigned char*) password, strlen(password)); - seed = gg_fix32(seed); - SHA1_Update(&ctx, (uint8_t*) &seed, 4); - - SHA1_Final(result, &ctx); -} -