#ifdef _WIN32 #include #else #include #include #endif #include #include #include #include #include "md5.h" #include "tcp.h" #include "growl.h" static const char hex_table[] = "0123456789ABCDEF"; static char* string_to_hex_alloc(const char* str, int len) { int n, l; char* tmp = (char*)malloc(len * 2 + 1); memset(tmp, 0, len * 2 + 1); for (l = 0, n = 0; l < len; l++) { tmp[n++] = hex_table[(str[l] & 0xF0) >> 4]; tmp[n++] = hex_table[str[l] & 0x0F]; } return tmp; } int growl_init_ = 0; int growl_init() { if( growl_init_ == 0) { #ifdef _WIN32 WSADATA wsaData; if( WSAStartup( MAKEWORD( 2 , 0 ) , &wsaData) != 0 ) { return -1; } #endif srand(time(NULL)); growl_init_ = 1; } return 1; } void growl_shutdown() { if( growl_init_ == 1 ) { #ifdef _WIN32 WSACleanup(); #endif } } char* gen_salt_alloc(int count) { char* salt = (char*)malloc(count + 1); int n; for (n = 0; n < count; n++) salt[n] = (((int)rand()) % 255) + 1; salt[n] = 0; return salt; } char* gen_password_hash_alloc(const char* password, const char* salt) { md5_context md5ctx; char md5tmp[20]; char* md5digest; memset(md5tmp, 0, sizeof(md5tmp)); md5_starts(&md5ctx); md5_update(&md5ctx, (uint8_t*)password, strlen(password)); md5_update(&md5ctx, (uint8_t*)salt, strlen(salt)); md5_finish(&md5ctx, (uint8_t*)md5tmp); md5_starts(&md5ctx); md5_update(&md5ctx, (uint8_t*)md5tmp, 16); md5_finish(&md5ctx, (uint8_t*)md5tmp); md5digest = string_to_hex_alloc(md5tmp, 16); return md5digest; } char *growl_generate_authheader_alloc(const char*const password) { char* salt; char* salthash; char* keyhash; char* authheader = NULL; if (password) { salt = gen_salt_alloc(8); keyhash = gen_password_hash_alloc(password, salt); salthash = string_to_hex_alloc(salt, 8); free(salt); authheader = (char*)malloc(strlen(keyhash) + strlen(salthash) + 7); sprintf(authheader, " MD5:%s.%s", keyhash, salthash); free(salthash); free(keyhash); } return authheader; } int growl_tcp_register( const char *const server , const char *const appname , const char **const notifications , const int notifications_count , const char *const password, const char* const icon ) { int sock = -1; int i=0; char *authheader; growl_init(); authheader = growl_generate_authheader_alloc(password); sock = growl_tcp_open(server); if (sock == -1) goto leave; growl_tcp_write(sock, "GNTP/1.0 REGISTER NONE %s", authheader ? authheader : ""); growl_tcp_write(sock, "Application-Name: %s ", appname); if(icon) growl_tcp_write(sock, "Application-Icon: %s ", icon); growl_tcp_write(sock, "Notifications-Count: %d", notifications_count); growl_tcp_write(sock, "" ); for(i=0;i