int hmac_md5 (const void *key, size_t keylen, const void *in, size_t inlen, void *resbuf) { struct md5_ctx inner; struct md5_ctx outer; char optkeybuf[16]; char block[64]; char innerhash[16]; /* Reduce the key's size, so that it becomes <= 64 bytes large. */ if (keylen > 64) { struct md5_ctx keyhash; md5_init_ctx (&keyhash); md5_process_bytes (key, keylen, &keyhash); md5_finish_ctx (&keyhash, optkeybuf); key = optkeybuf; keylen = 16; } /* Compute INNERHASH from KEY and IN. */ md5_init_ctx (&inner); memset (block, IPAD, sizeof (block)); memxor (block, key, keylen); md5_process_block (block, 64, &inner); md5_process_bytes (in, inlen, &inner); md5_finish_ctx (&inner, innerhash); /* Compute result from KEY and INNERHASH. */ md5_init_ctx (&outer); memset (block, OPAD, sizeof (block)); memxor (block, key, keylen); md5_process_block (block, 64, &outer); md5_process_bytes (innerhash, 16, &outer); md5_finish_ctx (&outer, resbuf); return 0; }
int main (int argc, char ** argv) { struct md5_ctx ctx; unsigned char result[16]; int i; if (argc < 2) { usage (); return 1; } md5_init_ctx (&ctx); for (i = 1; i < argc; i++) dosum (&ctx, argv[i]); md5_finish_ctx (&ctx, result); puts ("#include \"config.h\""); puts ("#include \"system.h\""); fputs ("EXPORTED_CONST unsigned char executable_checksum[16] = { ", stdout); for (i = 0; i < 16; i++) printf ("0x%02x%s", result[i], i == 15 ? " };\n" : ", "); return 0; }
/* find the initial vector required to evilize FILE, return it in IV. Returns 0 on success, 1 if crib was not found. */ static int find_iv(FILE *fin, unsigned int IV[4]) { struct md5_ctx ctx; char buf[64]; int r; int i; md5_init_ctx(&ctx); while (1) { r = fread(buf, 1, 64, fin); if (r < 64) { return 1; } for (i=0; i<64; i++) { if (memcmp(buf, crib+i, 64) == 0) { goto crib_found; } } md5_process_block(buf, 64, &ctx); } crib_found: /* find md5 collision for the given ctx initial value */ IV[0] = ctx.A; IV[1] = ctx.B; IV[2] = ctx.C; IV[3] = ctx.D; return 0; }
struct ne_md5_ctx * ne_md5_create_ctx(void) { struct md5_ctx *ctx = ne_malloc(sizeof *ctx); md5_init_ctx(ctx); return ctx; }
OOP MD5AllocOOP (void) { struct md5_ctx ctx; md5_init_ctx (&ctx); return vmProxy->byteArrayToOOP ((char *) &ctx, sizeof (ctx)); }
Gc_rc gc_hash_open (Gc_hash hash, Gc_hash_mode mode, gc_hash_handle * outhandle) { _gc_hash_ctx *ctx; Gc_rc rc = GC_OK; ctx = calloc (sizeof (*ctx), 1); ctx->alg = hash; ctx->mode = mode; switch (hash) { #ifdef GC_USE_MD2 case GC_MD2: md2_init_ctx (&ctx->md2Context); break; #endif #ifdef GC_USE_MD4 case GC_MD4: md4_init_ctx (&ctx->md4Context); break; #endif #ifdef GC_USE_MD5 case GC_MD5: md5_init_ctx (&ctx->md5Context); break; #endif #ifdef GC_USE_SHA1 case GC_SHA1: sha1_init_ctx (&ctx->sha1Context); break; #endif default: rc = GC_INVALID_HASH; break; } switch (mode) { case 0: break; default: rc = GC_INVALID_HASH; break; } if (rc == GC_OK) *outhandle = ctx; else free (ctx); return rc; }
int DVDDiscID( dvd_reader_t *dvd, unsigned char *discid ) { struct md5_ctx ctx; int title; int nr_of_files = 0; int tmp_errno; int nofiles_errno = ENOENT; /* Check arguments. */ if( dvd == NULL || discid == NULL ) { errno = EINVAL; return -1; } /* Go through the first 10 IFO:s, in order, * and md5sum them, i.e VIDEO_TS.IFO and VTS_0?_0.IFO */ md5_init_ctx( &ctx ); for( title = 0; title < 10; title++ ) { dvd_file_t *dvd_file = DVDOpenFile( dvd, title, DVD_READ_INFO_FILE ); if( dvd_file != NULL ) { ssize_t bytes_read; size_t file_size = dvd_file->filesize * DVD_VIDEO_LB_LEN; char *buffer = malloc( file_size ); nr_of_files++; if( buffer == NULL ) { /* errno will be set to ENOMEM by malloc */ return -1; } bytes_read = DVDReadBytes( dvd_file, buffer, file_size ); if( bytes_read != file_size ) { tmp_errno = errno; if(dvd->verbose >= 1) { fprintf( stderr, "libdvdread: DVDDiscId read returned %d bytes" ", wanted %d\n", (int)bytes_read, (int)file_size ); } free(buffer); DVDCloseFile( dvd_file ); errno = tmp_errno; return -1; } md5_process_bytes( buffer, file_size, &ctx ); DVDCloseFile( dvd_file ); free( buffer ); } else { if(errno != ENOENT) { nofiles_errno = errno; } } } md5_finish_ctx( &ctx, discid ); if(nr_of_files == 0) { errno = nofiles_errno; return -1; } return 0; }
void MD5::Init(unsigned int key1, unsigned int key2, unsigned int key3, unsigned int key4) { md5_init_ctx(&context); context.A = key1; context.B = key2; context.C = key3; context.D = key4; }
void hmac_md5 (const void *msg, size_t msg_len, const void *key, size_t key_len, void *digest) { struct md5_ctx ctx; /* inner padding - key XORd with ipad * outer padding - key XORd with opad */ unsigned char k_ipad[65], k_opad[65]; int i; /* if key is longer than 64 bytes reset it to key=MD5(key) */ if (key_len > 64) { struct md5_ctx tmp_ctx; char tk[16]; md5_init_ctx(&tmp_ctx); md5_process_bytes(key, key_len, &tmp_ctx); md5_finish_ctx(&tmp_ctx, tk); key = tk; key_len = 16; } memset (k_ipad, '\0', sizeof (k_ipad)); memset (k_opad, '\0', sizeof (k_opad)); memcpy (k_ipad, key, key_len); memcpy (k_opad, key, key_len); /* XOR key with ipad and opad values */ for (i = 0; i < 64; i++) { k_ipad[i] ^= 0x36; k_opad[i] ^= 0x5c; } /* perform inner MD5 */ md5_init_ctx(&ctx); /* init context for 1st pass */ md5_process_bytes(k_ipad, 64, &ctx); /* start with inner pad */ md5_process_bytes(msg, msg_len, &ctx); /* then text of datagram */ md5_finish_ctx(&ctx, digest); /* finish up 1st pass */ /* perform outer MD5 */ md5_init_ctx(&ctx); /* init context for 1st pass */ md5_process_bytes(k_opad, 64, &ctx); /* start with outer pad */ md5_process_bytes(digest, 16, &ctx); /* then results of the 1st hash */ md5_finish_ctx(&ctx, digest); /* finish up 2st pass */ }
static void hmac_md5(const unsigned char *data, int data_len, const unsigned char *key, int key_len, unsigned char *digest) { struct md5_ctx ctx; unsigned char k_ipad[65]; unsigned char k_opad[65]; unsigned char tk[16]; int i; if (key_len > 64) { struct md5_ctx tctx; md5_init_ctx(&tctx); md5_process_bytes(key, key_len, &tctx); md5_finish_ctx(&tctx, tk); key = tk; key_len = 16; } memset(k_ipad, 0, sizeof(k_ipad)); memset(k_opad, 0, sizeof(k_opad)); memcpy(k_ipad, key, key_len); memcpy(k_opad, key, key_len); for (i = 0; i < 64; i++) { k_ipad[i] ^= 0x36; k_opad[i] ^= 0x5c; } md5_init_ctx(&ctx); md5_process_bytes(k_ipad, 64, &ctx); md5_process_bytes(data, data_len, &ctx); md5_finish_ctx(&ctx, digest); md5_init_ctx(&ctx); md5_process_bytes(k_opad, 64, &ctx); md5_process_bytes(digest, 16, &ctx); md5_finish_ctx(&ctx, digest); }
int DVDDiscID( dvd_reader_t *dvd, unsigned char *discid ) { struct md5_ctx ctx; int title; int nr_of_files = 0; /* Check arguments. */ if( dvd == NULL || discid == NULL ) return 0; /* Go through the first 10 IFO:s, in order, * and md5sum them, i.e VIDEO_TS.IFO and VTS_0?_0.IFO */ md5_init_ctx( &ctx ); for( title = 0; title < 10; title++ ) { dvd_file_t *dvd_file = DVDOpenFile( dvd, title, DVD_READ_INFO_FILE ); if( dvd_file != NULL ) { ssize_t bytes_read; size_t file_size = dvd_file->filesize * DVD_VIDEO_LB_LEN; char *buffer_base = malloc( file_size + 2048 ); char *buffer = (char *)(((uintptr_t)buffer_base & ~((uintptr_t)2047)) + 2048); if( buffer_base == NULL ) { DVDCloseFile( dvd_file ); fprintf( stderr, "libdvdread: DVDDiscId, failed to " "allocate memory for file read!\n" ); return -1; } bytes_read = DVDReadBytes( dvd_file, buffer, file_size ); if( bytes_read != file_size ) { fprintf( stderr, "libdvdread: DVDDiscId read returned %zd bytes" ", wanted %zd\n", bytes_read, file_size ); DVDCloseFile( dvd_file ); free( buffer_base ); return -1; } md5_process_bytes( buffer, file_size, &ctx ); DVDCloseFile( dvd_file ); free( buffer_base ); nr_of_files++; } } md5_finish_ctx( &ctx, discid ); if(!nr_of_files) return -1; return 0; }
void gen_md5_init (gen_md5_context *ctx) { gen_md5_context_imp *ctx_imp = &ctx->imp; #ifdef HAVE_BUILTIN_MD5 md5_init_ctx (ctx_imp); #endif #ifdef HAVE_SOLARIS_MD5 MD5Init (ctx_imp); #endif #ifdef HAVE_OPENSSL_MD5 MD5_Init (ctx_imp); #endif }
static void apop_auth(const char *user, const char *pass) { int i; struct md5_ctx md5context; unsigned char md5digest[16]; char buf[sizeof(md5digest) * 2 + 1]; char *p; md5_init_ctx(&md5context); md5_process_bytes(msgid, strlen(msgid), &md5context); md5_process_bytes(pass, strlen(pass), &md5context); md5_finish_ctx(&md5context, md5digest); for (i = 0, p = buf; i < 16; i++, p += 2) sprintf(p, "%02x", md5digest[i]); *p = 0; stream_printf(iostr, "AUTH %s %s\r\n", user, buf); dict_read_reply(); assert_status("230"); }
header_cache_t * mutt_hcache_open(const char *path, const char *folder, hcache_namer_t namer) { struct header_cache *h = safe_calloc(1, sizeof (struct header_cache)); int (*hcache_open) (struct header_cache* h, const char* path); struct stat sb; #if HAVE_QDBM hcache_open = hcache_open_qdbm; #elif HAVE_TC hcache_open= hcache_open_tc; #elif HAVE_GDBM hcache_open = hcache_open_gdbm; #elif HAVE_DB4 hcache_open = hcache_open_db4; #endif /* Calculate the current hcache version from dynamic configuration */ if (hcachever == 0x0) { union { unsigned char charval[16]; unsigned int intval; } digest; struct md5_ctx ctx; SPAM_LIST *spam; RX_LIST *nospam; hcachever = HCACHEVER; md5_init_ctx(&ctx); /* Seed with the compiled-in header structure hash */ md5_process_bytes(&hcachever, sizeof(hcachever), &ctx); /* Mix in user's spam list */ for (spam = SpamList; spam; spam = spam->next) { md5_process_bytes(spam->rx->pattern, strlen(spam->rx->pattern), &ctx); md5_process_bytes(spam->template, strlen(spam->template), &ctx);
/* Start a new request. */ void http_auth_new_request(http_auth_session *sess, const char *method, const char *uri, const char *body_buffer, FILE *body_stream) { if (!sess->can_handle) { DEBUG(DEBUG_HTTPAUTH, "Not handling session.\n"); } else if (!is_in_domain(sess, uri)) { /* We have moved out of the authentication domain */ DEBUG(DEBUG_HTTPAUTH, "URI %s outside session domain, not handling.\n", uri); sess->will_handle = 0; } else { DEBUG(DEBUG_HTTPAUTH, "URI %s inside session domain, will handle.\n", uri); sess->will_handle = 1; sess->uri = uri; sess->method = method; sess->got_body = (body_buffer!=NULL) || (body_stream!=NULL); sess->body_buffer = body_buffer; sess->body_stream = body_stream; md5_init_ctx(&sess->response_body); } }
/* Play a file (disk file) using the given decoder. next_file is precached. */ static void play_file (const char *file, const struct decoder *f, const char *next_file, struct out_buf *out_buf) { void *decoder_data; struct sound_params sound_params = { 0, 0, 0 }; float already_decoded_time; struct md5_data md5; #if !defined(NDEBUG) && defined(DEBUG) md5.okay = true; md5.len = 0; md5_init_ctx (&md5.ctx); #endif out_buf_reset (out_buf); precache_wait (&precache); if (precache.ok && strcmp(precache.file, file)) { logit ("The precached file is not the file we want."); precache.f->close (precache.decoder_data); precache_reset (&precache); } if (precache.ok && !strcmp(precache.file, file)) { struct decoder_error err; logit ("Using precached file"); assert (f == precache.f); sound_params = precache.sound_params; decoder_data = precache.decoder_data; set_info_channels (sound_params.channels); set_info_rate (sound_params.rate / 1000); if (!audio_open(&sound_params)) { md5.okay = false; precache.f->close (precache.decoder_data); precache_reset (&precache); return; } #if !defined(NDEBUG) && defined(DEBUG) md5.len += precache.buf_fill; md5_process_bytes (precache.buf, precache.buf_fill, &md5.ctx); #endif audio_send_buf (precache.buf, precache.buf_fill); precache.f->get_error (precache.decoder_data, &err); if (err.type != ERROR_OK) { md5.okay = false; if (err.type != ERROR_STREAM || options_get_int( "ShowStreamErrors")) error ("%s", err.err); decoder_error_clear (&err); } already_decoded_time = precache.decoded_time; if(f->get_avg_bitrate) set_info_avg_bitrate (f->get_avg_bitrate(decoder_data)); else set_info_avg_bitrate (0); bitrate_list_init (&bitrate_list); bitrate_list.head = precache.bitrate_list.head; bitrate_list.tail = precache.bitrate_list.tail; /* don't free list elements when reseting precache */ precache.bitrate_list.head = NULL; precache.bitrate_list.tail = NULL; } else { struct decoder_error err; status_msg ("Opening..."); decoder_data = f->open(file); f->get_error (decoder_data, &err); if (err.type != ERROR_OK) { f->close (decoder_data); status_msg (""); error ("%s", err.err); decoder_error_clear (&err); logit ("Can't open file, exiting"); return; } already_decoded_time = 0.0; if(f->get_avg_bitrate) set_info_avg_bitrate (f->get_avg_bitrate(decoder_data)); bitrate_list_init (&bitrate_list); } audio_plist_set_time (file, f->get_duration(decoder_data)); audio_state_started_playing (); precache_reset (&precache); decode_loop (f, decoder_data, next_file, out_buf, &sound_params, &md5, already_decoded_time); #if !defined(NDEBUG) && defined(DEBUG) if (md5.okay) { uint8_t buf[MD5_DIGEST_SIZE]; md5_finish_ctx (&md5.ctx, buf); log_md5_sum (file, sound_params, f, buf, md5.len); } #endif }
extern void ne_md5_reset_ctx(struct ne_md5_ctx *ctx) { md5_init_ctx(ctx); }
/*! Start MD5 accumulation. Set bit count to 0 and buffer to mysterious initialization constants. */ void Md5::init () { md5_init_ctx (&ctx); }
void stat_server_read(void) { int n; char *p; int do_close = 0; char *salt, *servername; n = READ(global.stat_server_fd, Buf, sizeof(Buf)); if(n <= 0) { if(n == -1) logerr("stat_server_read", "read"); log_message_level( LOG_LEVEL_ERROR, "stat_server_read: got hangup"); do_close = 1; } else { /* find end of line */ p = strpbrk(Buf, "\r\n"); if(*p) *p = 0; p = Buf; n = atoi(Buf); if(n == 220) { /* got connect * first, save the salt */ next_arg(&p); salt = next_arg(&p); if(!salt) { log_message_level( LOG_LEVEL_ERROR, "stat_server_read:unable to get salt string"); strcpy(Buf, "QUIT\r\n"); WRITE(global.stat_server_fd, Buf, strlen(Buf)); } else { if(stat_server_salt) FREE(stat_server_salt); stat_server_salt = STRDUP(salt); snprintf(Buf, sizeof(Buf), "USER %s\r\n", global.stat_user); WRITE(global.stat_server_fd, Buf, strlen(Buf)); } } else if(n == 221) { /* server hangup */ do_close = 1; } else if(n == 300) { struct md5_ctx md; char hash[33]; md5_init_ctx(&md); md5_process_bytes(stat_server_salt, strlen(stat_server_salt), &md); md5_process_bytes(global.stat_pass, strlen(global.stat_pass), &md); md5_finish_ctx(&md, hash); expand_hex(hash, 16); hash[32] = 0; snprintf(Buf, sizeof(Buf), "PASS %s\r\n", hash); WRITE(global.stat_server_fd, Buf, strlen(Buf)); } else if(n == 201) { /* auth complete */ log_message_level( LOG_LEVEL_SERVER, "stat_server_read: logged in"); /* send updated ip:port in case we are a dynamic server */ snprintf(Buf, sizeof(Buf), "IPPORT %s %s %d\r\n",global.report_name, global.report_ip, global.report_port); WRITE(global.stat_server_fd, Buf, strlen(Buf)); /* force immediate update */ stat_server_push(); } /* The >= comparison made the comparison for == 400 some lines below not to work any more. So dynamic server addresses are not updated any more. But this solution is cumbersome - to say the least. Is there any better - and ofc any quicker detection of an ip address change possible? Now it takes up to stats_click seconds for a hub to recognize the change. */ else if(n / 100 > 4) { /* something failed */ log_message_level( LOG_LEVEL_SERVER, "stat_server_read:%s", Buf); strcpy(Buf, "QUIT\r\n"); WRITE(global.stat_server_fd, Buf, strlen(Buf)); } /* this part is needed if a server owner wants to use an alias usually server aliases are not resolvable - leodav */ else if(n == 400) { servername = lookup_hostname2(); log_message_level( LOG_LEVEL_SERVER, "stat_server_read:%s", Buf); strcpy(Buf, "QUIT\r\n"); WRITE(global.stat_server_fd, Buf, strlen(Buf)); global.serverIP = lookup_ip(servername); global.report_ip = STRDUP(my_ntoa(global.serverIP)); log_message_level( LOG_LEVEL_ERROR, "napigator.c:debug: %s", servername); } else if(n == 200) { /* stats updated successfully */ } else { log_message_level( LOG_LEVEL_ERROR, "stat_server_read: unhandled:%s", Buf); } } if(do_close) { log_message_level( LOG_LEVEL_SERVER, "stat_server_read: closing connection"); CLOSE(global.stat_server_fd); #if HAVE_POLL remove_fd(global.stat_server_fd); #else FD_CLR(global.stat_server_fd, &global.read_fds); FD_CLR(global.stat_server_fd, &global.write_fds); #endif global.stat_server_fd = INVALID_SOCKET; } }
void guid_init(void) { size_t bytes = 0; ENTER(""); /* Not needed; taken care of on first malloc. * guid_memchunk_init(); */ md5_init_ctx(&guid_context); /* entropy pool * FIXME /dev/urandom doesn't exist on Windows. We should * use the Windows native CryptGenRandom or RtlGenRandom * functions. See * http://en.wikipedia.org/wiki/CryptGenRandom */ bytes += init_from_file ("/dev/urandom", 512); /* files * FIXME none of these directories make sense on * Windows. We should figure out some proper * alternatives there. */ { const char * files[] = { "/etc/passwd", "/proc/loadavg", "/proc/meminfo", "/proc/net/dev", "/proc/rtc", "/proc/self/environ", "/proc/self/stat", "/proc/stat", "/proc/uptime", NULL }; int i; for (i = 0; files[i] != NULL; i++) bytes += init_from_file(files[i], BLOCKSIZE); } /* directories * Note: P_tmpdir is set to "\" by mingw (Windows) This seems to * trigger unwanted network access attempts (see bug #521817). * So on Windows we explicitly set the temporary directory. * FIXME other than "c:/temp" none of these directories make sense on * Windows. We should figure out some proper * alternatives there. */ { const char * dirname; const char * dirs[] = { "/proc", #ifndef G_OS_WIN32 P_tmpdir, #else "c:/temp", #endif "/var/lock", "/var/log", "/var/mail", "/var/spool/mail", "/var/run", NULL }; int i; for (i = 0; dirs[i] != NULL; i++) bytes += init_from_dir(dirs[i], 32); dirname = g_get_home_dir(); if (dirname != NULL) bytes += init_from_dir(dirname, 32); } /* process and parent ids */ { #ifdef HAVE_UNISTD_H pid_t pid; pid = getpid(); md5_process_bytes(&pid, sizeof(pid), &guid_context); bytes += sizeof(pid); #ifdef HAVE_GETPPID pid = getppid(); md5_process_bytes(&pid, sizeof(pid), &guid_context); bytes += sizeof(pid); #endif #endif } /* user info */ { #ifdef HAVE_GETUID uid_t uid; gid_t gid; char *s; s = getlogin(); if (s != NULL) { md5_process_bytes(s, strlen(s), &guid_context); bytes += strlen(s); } uid = getuid(); md5_process_bytes(&uid, sizeof(uid), &guid_context); bytes += sizeof(uid); gid = getgid(); md5_process_bytes(&gid, sizeof(gid), &guid_context); bytes += sizeof(gid); #endif } /* host info */ { #ifdef HAVE_GETHOSTNAME char string[1024]; memset(string, 0, sizeof(string)); gethostname(string, sizeof(string)); md5_process_bytes(string, sizeof(string), &guid_context); bytes += sizeof(string); #endif } /* plain old random */ { int n, i; srand((unsigned int) gnc_time (NULL)); for (i = 0; i < 32; i++) { n = rand(); md5_process_bytes(&n, sizeof(n), &guid_context); bytes += sizeof(n); } } /* time in secs and clock ticks */ bytes += init_from_time(); PINFO ("got %" G_GUINT64_FORMAT " bytes", (guint64) bytes); if (bytes < THRESHOLD) PWARN("only got %" G_GUINT64_FORMAT " bytes.\n" "The identifiers might not be very random.\n", (guint64)bytes); guid_initialized = TRUE; LEAVE(); }
/* This entry point is equivalent to the `crypt' function in Unix libcs. */ char * __md5_crypt_r (const char *key, const char *salt, char *buffer, int buflen) { unsigned char alt_result[16] __attribute__ ((__aligned__ (__alignof__ (md5_uint32)))); size_t salt_len; size_t key_len; size_t cnt; char *cp; char *copied_key = NULL; char *copied_salt = NULL; char *free_key = NULL; size_t alloca_used = 0; /* Find beginning of salt string. The prefix should normally always be present. Just in case it is not. */ if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0) /* Skip salt prefix. */ salt += sizeof (md5_salt_prefix) - 1; salt_len = MIN (strcspn (salt, "$"), 8); key_len = strlen (key); if ((key - (char *) 0) % __alignof__ (md5_uint32) != 0) { char *tmp; if (__libc_use_alloca (alloca_used + key_len + __alignof__ (md5_uint32))) tmp = (char *) alloca (key_len + __alignof__ (md5_uint32)); else { free_key = tmp = (char *) malloc (key_len + __alignof__ (md5_uint32)); if (tmp == NULL) return NULL; } key = copied_key = memcpy (tmp + __alignof__ (md5_uint32) - (tmp - (char *) 0) % __alignof__ (md5_uint32), key, key_len); assert ((key - (char *) 0) % __alignof__ (md5_uint32) == 0); } if ((salt - (char *) 0) % __alignof__ (md5_uint32) != 0) { char *tmp = (char *) alloca (salt_len + __alignof__ (md5_uint32)); salt = copied_salt = memcpy (tmp + __alignof__ (md5_uint32) - (tmp - (char *) 0) % __alignof__ (md5_uint32), salt, salt_len); assert ((salt - (char *) 0) % __alignof__ (md5_uint32) == 0); } #ifdef USE_NSS /* Initialize libfreebl3. */ NSSLOWInitContext *nss_ictx = NSSLOW_Init (); if (nss_ictx == NULL) { free (free_key); return NULL; } NSSLOWHASHContext *nss_ctx = NULL; NSSLOWHASHContext *nss_alt_ctx = NULL; #else struct md5_ctx ctx; struct md5_ctx alt_ctx; #endif /* Prepare for the real work. */ md5_init_ctx (&ctx, nss_ctx); /* Add the key string. */ md5_process_bytes (key, key_len, &ctx, nss_ctx); /* Because the SALT argument need not always have the salt prefix we add it separately. */ md5_process_bytes (md5_salt_prefix, sizeof (md5_salt_prefix) - 1, &ctx, nss_ctx); /* The last part is the salt string. This must be at most 8 characters and it ends at the first `$' character (for compatibility with existing implementations). */ md5_process_bytes (salt, salt_len, &ctx, nss_ctx); /* Compute alternate MD5 sum with input KEY, SALT, and KEY. The final result will be added to the first context. */ md5_init_ctx (&alt_ctx, nss_alt_ctx); /* Add key. */ md5_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx); /* Add salt. */ md5_process_bytes (salt, salt_len, &alt_ctx, nss_alt_ctx); /* Add key again. */ md5_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx); /* Now get result of this (16 bytes) and add it to the other context. */ md5_finish_ctx (&alt_ctx, nss_alt_ctx, alt_result); /* Add for any character in the key one byte of the alternate sum. */ for (cnt = key_len; cnt > 16; cnt -= 16) md5_process_bytes (alt_result, 16, &ctx, nss_ctx); md5_process_bytes (alt_result, cnt, &ctx, nss_ctx); /* For the following code we need a NUL byte. */ *alt_result = '\0'; /* The original implementation now does something weird: for every 1 bit in the key the first 0 is added to the buffer, for every 0 bit the first character of the key. This does not seem to be what was intended but we have to follow this to be compatible. */ for (cnt = key_len; cnt > 0; cnt >>= 1) md5_process_bytes ((cnt & 1) != 0 ? (const void *) alt_result : (const void *) key, 1, &ctx, nss_ctx); /* Create intermediate result. */ md5_finish_ctx (&ctx, nss_ctx, alt_result); /* Now comes another weirdness. In fear of password crackers here comes a quite long loop which just processes the output of the previous round again. We cannot ignore this here. */ for (cnt = 0; cnt < 1000; ++cnt) { /* New context. */ md5_init_ctx (&ctx, nss_ctx); /* Add key or last result. */ if ((cnt & 1) != 0) md5_process_bytes (key, key_len, &ctx, nss_ctx); else md5_process_bytes (alt_result, 16, &ctx, nss_ctx); /* Add salt for numbers not divisible by 3. */ if (cnt % 3 != 0) md5_process_bytes (salt, salt_len, &ctx, nss_ctx); /* Add key for numbers not divisible by 7. */ if (cnt % 7 != 0) md5_process_bytes (key, key_len, &ctx, nss_ctx); /* Add key or last result. */ if ((cnt & 1) != 0) md5_process_bytes (alt_result, 16, &ctx, nss_ctx); else md5_process_bytes (key, key_len, &ctx, nss_ctx); /* Create intermediate result. */ md5_finish_ctx (&ctx, nss_ctx, alt_result); } #ifdef USE_NSS /* Free libfreebl3 resources. */ NSSLOW_Shutdown (nss_ictx); #endif /* Now we can construct the result string. It consists of three parts. */ cp = __stpncpy (buffer, md5_salt_prefix, MAX (0, buflen)); buflen -= sizeof (md5_salt_prefix) - 1; cp = __stpncpy (cp, salt, MIN ((size_t) MAX (0, buflen), salt_len)); buflen -= MIN ((size_t) MAX (0, buflen), salt_len); if (buflen > 0) { *cp++ = '$'; --buflen; } __b64_from_24bit (&cp, &buflen, alt_result[0], alt_result[6], alt_result[12], 4); __b64_from_24bit (&cp, &buflen, alt_result[1], alt_result[7], alt_result[13], 4); __b64_from_24bit (&cp, &buflen, alt_result[2], alt_result[8], alt_result[14], 4); __b64_from_24bit (&cp, &buflen, alt_result[3], alt_result[9], alt_result[15], 4); __b64_from_24bit (&cp, &buflen, alt_result[4], alt_result[10], alt_result[5], 4); __b64_from_24bit (&cp, &buflen, 0, 0, alt_result[11], 2); if (buflen <= 0) { __set_errno (ERANGE); buffer = NULL; } else *cp = '\0'; /* Terminate the string. */ /* Clear the buffer for the intermediate result so that people attaching to processes or reading core dumps cannot get any information. We do it in this way to clear correct_words[] inside the MD5 implementation as well. */ #ifndef USE_NSS __md5_init_ctx (&ctx); __md5_finish_ctx (&ctx, alt_result); explicit_bzero (&ctx, sizeof (ctx)); explicit_bzero (&alt_ctx, sizeof (alt_ctx)); #endif if (copied_key != NULL) explicit_bzero (copied_key, key_len); if (copied_salt != NULL) explicit_bzero (copied_salt, salt_len); free (free_key); return buffer; }
/* Examine a digest challenge: return 0 if it is a valid Digest challenge, * else non-zero. */ static int digest_challenge(http_auth_session *sess, struct http_auth_chall *parms) { struct md5_ctx tmp; unsigned char tmp_md5[16]; char *password; /* Do we understand this challenge? */ if (parms->alg == http_auth_alg_unknown) { DEBUG(DEBUG_HTTPAUTH, "Unknown algorithm.\n"); return -1; } if ((parms->alg == http_auth_alg_md5_sess) && !(parms->qop_auth || parms->qop_auth_int)) { DEBUG(DEBUG_HTTPAUTH, "Server did not give qop with MD5-session alg.\n"); return -1; } if ((parms->realm==NULL) || (parms->nonce==NULL)) { DEBUG(DEBUG_HTTPAUTH, "Challenge missing nonce or realm.\n"); return -1; } if (parms->stale) { /* Just a stale response, don't need to get a new username/password */ DEBUG(DEBUG_HTTPAUTH, "Stale digest challenge.\n"); } else { /* Forget the old session details */ DEBUG(DEBUG_HTTPAUTH, "In digest challenge.\n"); clean_session(sess); sess->unq_realm = shave_string(parms->realm, '"'); /* Not a stale response: really need user authentication */ if (get_credentials(sess, &password)) { /* Failed to get credentials */ HTTP_FREE(sess->unq_realm); return -1; } } sess->alg = parms->alg; sess->scheme = http_auth_scheme_digest; sess->unq_nonce = shave_string(parms->nonce, '"'); sess->unq_cnonce = get_cnonce(); if (parms->domain) { if (parse_domain(sess, parms->domain)) { /* TODO: Handle the error? */ } } else { sess->domain = NULL; sess->domain_count = 0; } if (parms->opaque != NULL) { sess->opaque = ne_strdup(parms->opaque); /* don't strip the quotes */ } if (parms->got_qop) { /* What type of qop are we to apply to the message? */ DEBUG(DEBUG_HTTPAUTH, "Got qop directive.\n"); sess->nonce_count = 0; if (parms->qop_auth_int) { sess->qop = http_auth_qop_auth_int; } else { sess->qop = http_auth_qop_auth; } } else { /* No qop at all/ */ sess->qop = http_auth_qop_none; } if (!parms->stale) { /* Calculate H(A1). * tmp = H(unq(username-value) ":" unq(realm-value) ":" passwd) */ DEBUG(DEBUG_HTTPAUTH, "Calculating H(A1).\n"); md5_init_ctx(&tmp); md5_process_bytes(sess->username, strlen(sess->username), &tmp); md5_process_bytes(":", 1, &tmp); md5_process_bytes(sess->unq_realm, strlen(sess->unq_realm), &tmp); md5_process_bytes(":", 1, &tmp); if (password != NULL) md5_process_bytes(password, strlen(password), &tmp); md5_finish_ctx(&tmp, tmp_md5); if (sess->alg == http_auth_alg_md5_sess) { unsigned char a1_md5[16]; struct md5_ctx a1; char tmp_md5_ascii[33]; /* Now we calculate the SESSION H(A1) * A1 = H(...above...) ":" unq(nonce-value) ":" unq(cnonce-value) */ md5_to_ascii(tmp_md5, tmp_md5_ascii); md5_init_ctx(&a1); md5_process_bytes(tmp_md5_ascii, 32, &a1); md5_process_bytes(":", 1, &a1); md5_process_bytes(sess->unq_nonce, strlen(sess->unq_nonce), &a1); md5_process_bytes(":", 1, &a1); md5_process_bytes(sess->unq_cnonce, strlen(sess->unq_cnonce), &a1); md5_finish_ctx(&a1, a1_md5); md5_to_ascii(a1_md5, sess->h_a1); DEBUG(DEBUG_HTTPAUTH, "Session H(A1) is [%s]\n", sess->h_a1); } else { md5_to_ascii(tmp_md5, sess->h_a1); DEBUG(DEBUG_HTTPAUTH, "H(A1) is [%s]\n", sess->h_a1); } HTTP_FREE(password); } DEBUG(DEBUG_HTTPAUTH, "I like this Digest challenge.\n"); return 0; }
/* Return Digest authentication credentials header value for the given * session. */ static char *request_digest(http_auth_session *sess) { struct md5_ctx a2, rdig; unsigned char a2_md5[16], rdig_md5[16]; char a2_md5_ascii[33], rdig_md5_ascii[33]; char nc_value[9] = {0}, *ret; const char *qop_value; /* qop-value */ size_t retlen; /* Increase the nonce-count */ if (sess->qop != http_auth_qop_none) { sess->nonce_count++; snprintf(nc_value, 9, "%08x", sess->nonce_count); DEBUG(DEBUG_HTTPAUTH, "Nonce count is %d, nc is [%s]\n", sess->nonce_count, nc_value); } qop_value = qop_values[sess->qop]; /* Calculate H(A2). */ md5_init_ctx(&a2); md5_process_bytes(sess->method, strlen(sess->method), &a2); md5_process_bytes(":", 1, &a2); md5_process_bytes(sess->uri, strlen(sess->uri), &a2); if (sess->qop == http_auth_qop_auth_int) { /* Calculate H(entity-body) */ if (sess->got_body) { char tmp_md5_ascii[33]; unsigned char tmp_md5[16]; if (sess->body_stream != NULL) { DEBUG(DEBUG_HTTPAUTH, "Digesting body stream.\n"); md5_stream(sess->body_stream, tmp_md5); rewind(sess->body_stream); /* leave it at the beginning */ } else if (sess->body_buffer) { DEBUG(DEBUG_HTTPAUTH, "Digesting body buffer.\n"); md5_buffer(sess->body_buffer, strlen(sess->body_buffer), tmp_md5); } md5_to_ascii(tmp_md5, tmp_md5_ascii); DEBUG(DEBUG_HTTPAUTH, "H(entity-body) is [%s]\n", tmp_md5_ascii); /* Append to A2 */ md5_process_bytes(":", 1, &a2); md5_process_bytes(tmp_md5_ascii, 32, &a2); } else { /* No entity-body. */ DEBUG(DEBUG_HTTPAUTH, "Digesting empty entity-body.\n"); md5_process_bytes(":" DIGEST_MD5_EMPTY, 33, &a2); } } md5_finish_ctx(&a2, a2_md5); md5_to_ascii(a2_md5, a2_md5_ascii); DEBUG(DEBUG_HTTPAUTH, "H(A2): %s\n", a2_md5_ascii); DEBUG(DEBUG_HTTPAUTH, "Calculating Request-Digest.\n"); /* Now, calculation of the Request-Digest. * The first section is the regardless of qop value * H(A1) ":" unq(nonce-value) ":" */ md5_init_ctx(&rdig); /* Use the calculated H(A1) */ md5_process_bytes(sess->h_a1, 32, &rdig); md5_process_bytes(":", 1, &rdig); md5_process_bytes(sess->unq_nonce, strlen(sess->unq_nonce), &rdig); md5_process_bytes(":", 1, &rdig); if (sess->qop != http_auth_qop_none) { /* Add on: * nc-value ":" unq(cnonce-value) ":" unq(qop-value) ":" */ DEBUG(DEBUG_HTTPAUTH, "Have qop directive, digesting: [%s:%s:%s]\n", nc_value, sess->unq_cnonce, qop_value); md5_process_bytes(nc_value, 8, &rdig); md5_process_bytes(":", 1, &rdig); md5_process_bytes(sess->unq_cnonce, strlen(sess->unq_cnonce), &rdig); md5_process_bytes(":", 1, &rdig); /* Store a copy of this structure (see note below) */ sess->stored_rdig = rdig; md5_process_bytes(qop_value, strlen(qop_value), &rdig); md5_process_bytes(":", 1, &rdig); } else { /* Store a copy of this structure... we do this because the * calculation of the rspauth= field in the Auth-Info header * is the same as this digest, up to this point. */ sess->stored_rdig = rdig; } /* And finally, H(A2) */ md5_process_bytes(a2_md5_ascii, 32, &rdig); md5_finish_ctx(&rdig, rdig_md5); md5_to_ascii(rdig_md5, rdig_md5_ascii); /* Buffer size calculation. */ retlen = 6 /* Digest */ + 1 + 8 + 1 + 2 + strlen(sess->username) /* username="******" */ + 2 + 5 + 1 + 2 + strlen(sess->unq_realm) /* , realm="..." */ + 2 + 5 + 1 + 2 + strlen(sess->unq_nonce) /* , nonce="..." */ + 2 + 3 + 1 + 2 + strlen(sess->uri) /* , uri="..." */ + 2 + 8 + 1 + 2 + 32 /* , response="..." */ + 2 + 9 + 1 + 2 + strlen(algorithm_names[sess->alg]) /* , algorithm="..." */ ; if (sess->opaque != NULL) retlen += 2 + 6 + 1 + strlen(sess->opaque); /* , opaque=... */ if (sess->qop != http_auth_qop_none) retlen += 2 + 6 + 2 + 1 + strlen(sess->unq_cnonce) + /* , cnonce="..." */ 2 + 2 + 1 + 8 + /* , nc=... */ 2 + 3 + 1 + 2 + strlen(qop_values[sess->qop]) /* , qop="..." */ ; retlen += 2; /* \r\n */ DEBUG(DEBUG_HTTPAUTH, "Calculated length of buffer: %d\n", retlen); ret = ne_calloc(retlen + 1); sprintf(ret, "Digest username=\"%s\", realm=\"%s\"" ", nonce=\"%s\", uri=\"%s\", response=\"%s\"" ", algorithm=\"%s\"", sess->username, sess->unq_realm, sess->unq_nonce, sess->uri, rdig_md5_ascii, algorithm_names[sess->alg]); if (sess->opaque != NULL) { /* We never unquote it, so it's still quoted here */ strcat(ret, ", opaque="); strcat(ret, sess->opaque); } if (sess->qop != http_auth_qop_none) { /* Add in cnonce and nc-value fields */ strcat(ret, ", cnonce=\""); strcat(ret, sess->unq_cnonce); strcat(ret, "\", nc="); strcat(ret, nc_value); strcat(ret, ", qop=\""); strcat(ret, qop_values[sess->qop]); strcat(ret, "\""); } DEBUG(DEBUG_HTTPAUTH, "Digest header field value:\n%s\n", ret); strcat(ret, "\r\n"); DEBUG(DEBUG_HTTPAUTH, "Calculated length: %d, actual length: %d\n", retlen, strlen(ret)); return ret; }
/* Pass this the value of the 'Authentication-Info:' header field, if * one is received. * Returns: * 0 if it gives a valid authentication for the server * non-zero otherwise (don't believe the response in this case!). */ int http_auth_verify_response(http_auth_session *sess, const char *value) { char **pairs; http_auth_qop qop = http_auth_qop_none; char *nextnonce = NULL, /* for the nextnonce= value */ *rspauth = NULL, /* for the rspauth= value */ *cnonce = NULL, /* for the cnonce= value */ *nc = NULL, /* for the nc= value */ *unquoted, *qop_value = NULL; int n, nonce_count, okay; if (!sess->will_handle) { /* Ignore it */ return 0; } if (sess->scheme != http_auth_scheme_digest) { DEBUG(DEBUG_HTTPAUTH, "Found Auth-Info header not in response to Digest credentials - dodgy.\n"); return -1; } DEBUG (DEBUG_HTTPAUTH, "Auth-Info header: %s\n", value); pairs = pair_string(value, ',', '=', HTTP_QUOTES, HTTP_WHITESPACE); for (n = 0; pairs[n]!=NULL; n+=2) { unquoted = shave_string(pairs[n+1], '"'); if (strcasecmp(pairs[n], "qop") == 0) { qop_value = ne_strdup(pairs[n+1]); if (strcasecmp(pairs[n+1], "auth-int") == 0) { qop = http_auth_qop_auth_int; } else if (strcasecmp(pairs[n+1], "auth") == 0) { qop = http_auth_qop_auth; } else { qop = http_auth_qop_none; } } else if (strcasecmp(pairs[n], "nextnonce") == 0) { nextnonce = ne_strdup(unquoted); } else if (strcasecmp(pairs[n], "rspauth") == 0) { rspauth = ne_strdup(unquoted); } else if (strcasecmp(pairs[n], "cnonce") == 0) { cnonce = ne_strdup(unquoted); } else if (strcasecmp(pairs[n], "nc") == 0) { nc = ne_strdup(pairs[n]); if (sscanf(pairs[n+1], "%x", &nonce_count) != 1) { DEBUG(DEBUG_HTTPAUTH, "Couldn't scan [%s] for nonce count.\n", pairs[n+1]); } else { DEBUG(DEBUG_HTTPAUTH, "Got nonce_count: %d\n", nonce_count); } } free(unquoted); } pair_string_free(pairs); /* Presume the worst */ okay = -1; if ((qop != http_auth_qop_none) && (qop_value != NULL)) { if ((rspauth == NULL) || (cnonce == NULL) || (nc == NULL)) { DEBUG(DEBUG_HTTPAUTH, "Missing rspauth, cnonce or nc with qop.\n"); } else { /* Have got rspauth, cnonce and nc */ if (strcmp(cnonce, sess->unq_cnonce) != 0) { DEBUG(DEBUG_HTTPAUTH, "Response cnonce doesn't match.\n"); } else if (nonce_count != sess->nonce_count) { DEBUG(DEBUG_HTTPAUTH, "Response nonce count doesn't match.\n"); } else { /* Calculate and check the response-digest value. * joe: IMO the spec is slightly ambiguous as to whether * we use the qop which WE sent, or the qop which THEY * sent... */ struct md5_ctx a2; unsigned char a2_md5[16], rdig_md5[16]; char a2_md5_ascii[33], rdig_md5_ascii[33]; DEBUG(DEBUG_HTTPAUTH, "Calculating response-digest.\n"); /* First off, H(A2) again. */ md5_init_ctx(&a2); md5_process_bytes(":", 1, &a2); md5_process_bytes(sess->uri, strlen(sess->uri), &a2); if (qop == http_auth_qop_auth_int) { unsigned char heb_md5[16]; char heb_md5_ascii[33]; /* Add on ":" H(entity-body) */ md5_finish_ctx(&sess->response_body, heb_md5); md5_to_ascii(heb_md5, heb_md5_ascii); md5_process_bytes(":", 1, &a2); md5_process_bytes(heb_md5_ascii, 32, &a2); DEBUG(DEBUG_HTTPAUTH, "Digested [:%s]\n", heb_md5_ascii); } md5_finish_ctx(&a2, a2_md5); md5_to_ascii(a2_md5, a2_md5_ascii); /* We have the stored digest-so-far of * H(A1) ":" unq(nonce-value) * [ ":" nc-value ":" unq(cnonce-value) ] for qop * in sess->stored_rdig, to save digesting them again. * */ if (qop != http_auth_qop_none) { /* Add in qop-value */ DEBUG(DEBUG_HTTPAUTH, "Digesting qop-value [%s:].\n", qop_value); md5_process_bytes(qop_value, strlen(qop_value), &sess->stored_rdig); md5_process_bytes(":", 1, &sess->stored_rdig); } /* Digest ":" H(A2) */ md5_process_bytes(a2_md5_ascii, 32, &sess->stored_rdig); /* All done */ md5_finish_ctx(&sess->stored_rdig, rdig_md5); md5_to_ascii(rdig_md5, rdig_md5_ascii); DEBUG(DEBUG_HTTPAUTH, "Calculated response-digest of: [%s]\n", rdig_md5_ascii); DEBUG(DEBUG_HTTPAUTH, "Given response-digest of: [%s]\n", rspauth); /* And... do they match? */ okay = (strcasecmp(rdig_md5_ascii, rspauth) == 0)?0:-1; DEBUG(DEBUG_HTTPAUTH, "Matched: %s\n", okay?"nope":"YES!"); } free(rspauth); free(cnonce); free(nc); } free(qop_value); } else { DEBUG(DEBUG_HTTPAUTH, "No qop directive, auth okay.\n"); okay = 0; } /* Check for a nextnonce */ if (nextnonce != NULL) { DEBUG(DEBUG_HTTPAUTH, "Found nextnonce of [%s].\n", nextnonce); if (sess->unq_nonce != NULL) free(sess->unq_nonce); sess->unq_nonce = nextnonce; } return okay; }
void MD5::Init() { md5_init_ctx(&context); }
/** * Simple RADIUS test. * * We send a Status-Server packet, and expect an Access-Accept or Accounting-Response packet. * * @author Alan deKok, <*****@*****.**> * */ int check_radius(Socket_T s) { int i, length, left; int secret_len; Port_T P; struct md5_ctx ctx; char *secret; unsigned char *attr; unsigned char digest[16]; unsigned char response[STRLEN]; unsigned char request[38] = { 0x0c, /** Status-Server */ 0x00, /* code. We always use zero. */ 0x00, /** packet length */ 0x26, 0x00, /** Request Authenticator */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, /** Message-Authenticator */ 0x12, /** length */ 0x00, /** contents of Message-Authenticator */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; ASSERT(s); switch (socket_get_type(s)) { case SOCK_DGRAM: break; default: LogError("RADIUS: unsupported socket type -- protocol test skipped\n"); return TRUE; } P = socket_get_Port(s); ASSERT(P); secret = (P->request ? P->request : "testing123"); secret_len = strlen(secret); /* Get 16 bytes of (very bad) random data */ for (i = 0; i < 16; i++) request[i + 4] = ((unsigned int)random()) & 0xff; /* sign the packet */ hmac_md5(request, sizeof(request), (unsigned char *)secret, secret_len, request + 22); if (socket_write(s, (unsigned char *)request, sizeof(request)) < 0) { LogError("RADIUS: error sending query -- %s\n", STRERROR); return FALSE; } /* Response should have at least 20 bytes */ length = socket_read(s, (unsigned char *)response, sizeof(response)); if (length < 20) { LogError("RADIUS: error receiving response -- %s\n", STRERROR); return FALSE; } /* Compare response code (should be Access-Accept or Accounting-Response) */ if ((response[0] != 2) && (response[0] != 5)) { LogError("RADIUS: Invalid reply code -- error occured\n"); return FALSE; } /* Compare packet ID (it should be the same as in our request): */ if (response[1] != 0x00) { LogError("RADIUS: ID mismatch\n"); return FALSE; } /* check length */ if (response[2] != 0) { LogError("RADIUS: message is too long\n"); return FALSE; } /* check length against packet data*/ if (response[3] != length) { LogError("RADIUS: message has invalid length\n"); return FALSE; } /* validate that it is a well-formed packet */ attr = response + 20; left = length - 20; while (left > 0) { if (left < 2) { LogError("RADIUS: message is malformed\n"); return FALSE; } if (attr[1] < 2) { LogError("RADIUS: message has invalid attribute length\n"); return FALSE; } if (attr[1] > left) { LogError("RADIUS: message has attribute that is too long\n"); return FALSE; } /* validate Message-Authenticator, if found */ if (attr[0] == 0x50) { /* FIXME: validate it */ } left -= attr[1]; } /* save the reply authenticator, and copy the request authenticator over */ memcpy(digest, response + 4, 16); memcpy(response + 4, request + 4, 16); md5_init_ctx(&ctx); md5_process_bytes(response, length, &ctx); md5_process_bytes(secret, secret_len, &ctx); md5_finish_ctx(&ctx, response + 4); if (memcmp(digest, response + 4, 16) != 0) LogError("RADIUS: message fails authentication\n"); return TRUE; }
static gint checkcert_cb(GWEN_GUI *gwen_gui, const GWEN_SSLCERTDESCR *cert, GWEN_IO_LAYER *io, guint32 guiid) { GncGWENGui *gui = GETDATA_GUI(gwen_gui); const gchar *hash, *status; struct md5_ctx md5_context; gchar cert_hash[16]; gchar *cert_hash_hex; gint retval, i; g_return_val_if_fail(gui && gui->accepted_certs, -1); ENTER("gui=%p, cert=%p", gui, cert); hash = GWEN_SslCertDescr_GetFingerPrint(cert); status = GWEN_SslCertDescr_GetStatusText(cert); /* Operate on an md5sum of the pair of hash and status */ md5_init_ctx(&md5_context); md5_process_bytes(hash, strlen(hash), &md5_context); md5_process_bytes(status, strlen(status), &md5_context); md5_finish_ctx(&md5_context, cert_hash); /* Did we get the permanently accepted certs from AqBanking? */ if (gui->permanently_accepted_certs) { /* Generate a hex string of the cert_hash for usage by AqBanking cert store */ cert_hash_hex = g_new0(gchar, 33); for (i = 0; i < 16; i++) g_snprintf(cert_hash_hex + 2 * i, 3, "%02X", (unsigned char)cert_hash[i]); retval = GWEN_DB_GetIntValue(gui->permanently_accepted_certs, cert_hash_hex, 0, -1); g_free(cert_hash_hex); if (retval == 0) { /* Certificate is marked as accepted in AqBanking's cert store */ LEAVE("Certificate accepted by AqBanking's permanent cert store"); return 0; } } else { g_warning("Can't check permanently accepted certs from invalid AqBanking cert store."); } if (g_hash_table_lookup(gui->accepted_certs, cert_hash)) { /* Certificate has been accepted by Gnucash before */ LEAVE("Automatically accepting certificate"); return 0; } retval = gui->builtin_checkcert(gwen_gui, cert, io, guiid); if (retval == 0) { /* Certificate has been accepted */ g_hash_table_insert(gui->accepted_certs, g_strdup(cert_hash), cert_hash); } LEAVE("retval=%d", retval); return retval; }
bfd_boolean generate_build_id (bfd *abfd, const char *style, checksum_fn checksum_contents, unsigned char *id_bits, int size ATTRIBUTE_UNUSED) { if (streq (style, "md5")) { struct md5_ctx ctx; md5_init_ctx (&ctx); if (!(*checksum_contents) (abfd, (sum_fn) &md5_process_bytes, &ctx)) return FALSE; md5_finish_ctx (&ctx, id_bits); } else if (streq (style, "sha1")) { struct sha1_ctx ctx; sha1_init_ctx (&ctx); if (!(*checksum_contents) (abfd, (sum_fn) &sha1_process_bytes, &ctx)) return FALSE; sha1_finish_ctx (&ctx, id_bits); } else if (streq (style, "uuid")) { #ifndef __MINGW32__ int n; int fd = open ("/dev/urandom", O_RDONLY); if (fd < 0) return FALSE; n = read (fd, id_bits, size); close (fd); if (n < size) return FALSE; #else /* __MINGW32__ */ typedef RPC_STATUS (RPC_ENTRY * UuidCreateFn) (UUID *); UUID uuid; UuidCreateFn uuid_create = 0; HMODULE rpc_library = LoadLibrary ("rpcrt4.dll"); if (!rpc_library) return FALSE; uuid_create = (UuidCreateFn) (void (WINAPI *)(void)) GetProcAddress (rpc_library, "UuidCreate"); if (!uuid_create) { FreeLibrary (rpc_library); return FALSE; } if (uuid_create (&uuid) != RPC_S_OK) { FreeLibrary (rpc_library); return FALSE; } FreeLibrary (rpc_library); memcpy (id_bits, &uuid, (size_t) size < sizeof (UUID) ? (size_t) size : sizeof (UUID)); #endif /* __MINGW32__ */ } else if (strneq (style, "0x", 2)) { /* ID is in string form (hex). Convert to bits. */ const char *id = style + 2; size_t n = 0; do { if (ISXDIGIT (id[0]) && ISXDIGIT (id[1])) { id_bits[n] = read_hex (*id++) << 4; id_bits[n++] |= read_hex (*id++); } else if (*id == '-' || *id == ':') ++id; else abort (); /* Should have been validated earlier. */ } while (*id != '\0'); } else abort (); /* Should have been validated earlier. */ return TRUE; }
/* Decompress an open file. Call fatal_return(() on error return the number of bytes that have been retrieved */ i64 runzip_fd(rzip_control *control, int fd_in, int fd_out, int fd_hist, i64 expected_size) { uchar md5_stored[MD5_DIGEST_SIZE]; struct timeval start,end; i64 total = 0, u; double tdiff; if (!NO_MD5) md5_init_ctx (&control->ctx); gettimeofday(&start,NULL); do { u = runzip_chunk(control, fd_in, expected_size, total); if (unlikely(u == -1)) { print_err("Failed to runzip_chunk in runzip_fd\n"); return -1; } total += u; if (TMP_OUTBUF) { if (unlikely(!flush_tmpoutbuf(control))) { print_err("Failed to flush_tmpoutbuf in runzip_fd\n"); return -1; } } else if (STDOUT) { if (unlikely(!dump_tmpoutfile(control, fd_out))) { print_err("Failed to dump_tmpoutfile in runzip_fd\n"); return -1; } } if (TMP_INBUF) clear_tmpinbuf(control); else if (STDIN && !DECOMPRESS) { if (unlikely(!clear_tmpinfile(control))) { print_err("Failed to clear_tmpinfile in runzip_fd\n"); return -1; } } } while (total < expected_size || (!expected_size && !control->eof)); gettimeofday(&end,NULL); if (!ENCRYPT) { tdiff = end.tv_sec - start.tv_sec; if (!tdiff) tdiff = 1; print_progress("\nAverage DeCompression Speed: %6.3fMB/s\n", (total / 1024 / 1024) / tdiff); } if (!NO_MD5) { int i,j; md5_finish_ctx (&control->ctx, control->md5_resblock); if (HAS_MD5) { i64 fdinend = seekto_fdinend(control); if (unlikely(fdinend == -1)) failure_return(("Failed to seekto_fdinend in rzip_fd\n"), -1); if (unlikely(seekto_fdin(control, fdinend - MD5_DIGEST_SIZE) == -1)) failure_return(("Failed to seekto_fdin in rzip_fd\n"), -1); if (unlikely(read_1g(control, fd_in, md5_stored, MD5_DIGEST_SIZE) != MD5_DIGEST_SIZE)) fatal_return(("Failed to read md5 data in runzip_fd\n"), -1); if (ENCRYPT) if (unlikely(!lrz_decrypt(control, md5_stored, MD5_DIGEST_SIZE, control->salt_pass))) return -1; for (i = 0; i < MD5_DIGEST_SIZE; i++) if (md5_stored[i] != control->md5_resblock[i]) { print_output("MD5 CHECK FAILED.\nStored:"); for (j = 0; j < MD5_DIGEST_SIZE; j++) print_output("%02x", md5_stored[j] & 0xFF); print_output("\nOutput file:"); for (j = 0; j < MD5_DIGEST_SIZE; j++) print_output("%02x", control->md5_resblock[j] & 0xFF); failure_return(("\n"), -1); } } if (HASH_CHECK || MAX_VERBOSE) { print_output("MD5: "); for (i = 0; i < MD5_DIGEST_SIZE; i++) print_output("%02x", control->md5_resblock[i] & 0xFF); print_output("\n"); } if (CHECK_FILE) { FILE *md5_fstream; int i, j; if (TMP_OUTBUF) close_tmpoutbuf(control); memcpy(md5_stored, control->md5_resblock, MD5_DIGEST_SIZE); if (unlikely(seekto_fdhist(control, 0) == -1)) fatal_return(("Failed to seekto_fdhist in runzip_fd\n"), -1); if (unlikely((md5_fstream = fdopen(fd_hist, "r")) == NULL)) fatal_return(("Failed to fdopen fd_hist in runzip_fd\n"), -1); if (unlikely(md5_stream(md5_fstream, control->md5_resblock))) fatal_return(("Failed to md5_stream in runzip_fd\n"), -1); /* We don't close the file here as it's closed in main */ for (i = 0; i < MD5_DIGEST_SIZE; i++) if (md5_stored[i] != control->md5_resblock[i]) { print_output("MD5 CHECK FAILED.\nStored:"); for (j = 0; j < MD5_DIGEST_SIZE; j++) print_output("%02x", md5_stored[j] & 0xFF); print_output("\nOutput file:"); for (j = 0; j < MD5_DIGEST_SIZE; j++) print_output("%02x", control->md5_resblock[j] & 0xFF); failure_return(("\n"), -1); } print_output("MD5 integrity of written file matches archive\n"); if (!HAS_MD5) print_output("Note this lrzip archive did not have a stored md5 value.\n" "The archive decompression was validated with crc32 and the md5 hash was " "calculated on decompression\n"); } } return total; }