Exemple #1
0
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;
}
Exemple #2
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;
}
Exemple #3
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;
}
Exemple #4
0
struct ne_md5_ctx *
ne_md5_create_ctx(void)
{
  struct md5_ctx *ctx = ne_malloc(sizeof *ctx);
  md5_init_ctx(ctx);
  return ctx;
}
Exemple #5
0
OOP
MD5AllocOOP (void)
{
  struct md5_ctx ctx;
  md5_init_ctx (&ctx);
  return vmProxy->byteArrayToOOP ((char *) &ctx, sizeof (ctx));
}
Exemple #6
0
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;
}
Exemple #7
0
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;
}
Exemple #8
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 */
}
Exemple #10
0
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);
}
Exemple #11
0
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;
}
Exemple #12
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
}
Exemple #13
0
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");
}
Exemple #14
0
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);
Exemple #15
0
/* 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);
    }
}
Exemple #16
0
/* 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
}
Exemple #17
0
extern void 
ne_md5_reset_ctx(struct ne_md5_ctx *ctx)
{
  md5_init_ctx(ctx);
}
Exemple #18
0
/*!
  Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
  initialization constants.
 */
void Md5::init ()
{
  md5_init_ctx (&ctx);
}
Exemple #19
0
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;
    }
}
Exemple #20
0
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();
}
Exemple #21
0
/* 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;
}
Exemple #22
0
/* 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;
}
Exemple #23
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;
}
Exemple #24
0
/* 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;
}
Exemple #25
0
void MD5::Init()
{
    md5_init_ctx(&context);
}
Exemple #26
0
/**
 *  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;
}
Exemple #27
0
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;
}
Exemple #28
0
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;
}
Exemple #29
0
/* 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;
}