Exemple #1
0
static size_t
init_from_time(void)
{
    size_t total;
    time64 time;
#ifdef HAVE_SYS_TIMES_H
    clock_t clocks;
    struct tms tms_buf;
#endif

    ENTER("");

    total = 0;

    time = gnc_time (NULL);
    md5_process_bytes(&time, sizeof(time), &guid_context);
    total += sizeof(time);

#ifdef HAVE_SYS_TIMES_H
    clocks = times(&tms_buf);
    md5_process_bytes(&clocks, sizeof(clocks), &guid_context);
    md5_process_bytes(&tms_buf, sizeof(tms_buf), &guid_context);
    total += sizeof(clocks) + sizeof(tms_buf);
#endif

    LEAVE("");
    return total;
}
Exemple #2
0
static size_t
init_from_dir(const char *dirname, unsigned int max_files)
{
    char filename[1024];
    const gchar *de;
    struct stat stats;
    size_t total;
    int result;
    GDir *dir;

    ENTER("dirname: %s", dirname);
    if (max_files <= 0)
    {
        LEAVE("max_files is 0 or less, skipping directory %s", dirname);
        return 0;
    }

    dir = g_dir_open(dirname, 0, NULL);
    if (dir == NULL)
    {
        LEAVE("unable to open directory %s", dirname);
        return 0;
    }

    total = 0;

    do
    {
        de = g_dir_read_name(dir);
        if (de == NULL)
            break;

        md5_process_bytes(de, strlen(de), &guid_context);
        total += strlen(de);

        result = g_snprintf(filename, sizeof(filename),
                            "%s/%s", dirname, de);
        if ((result < 0) || (result >= (int)sizeof(filename)))
            continue;

        memset(&stats, 0, sizeof(stats));
        if (g_stat(filename, &stats) != 0)
            continue;
        md5_process_bytes(&stats, sizeof(stats), &guid_context);
        total += sizeof(stats);

        max_files--;
    }
    while (max_files > 0);

    g_dir_close(dir);

    LEAVE("");
    return total;
}
Exemple #3
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 #4
0
static i64 unzip_literal(rzip_control *control, void *ss, i64 len, uint32 *cksum)
{
	i64 stream_read;
	uchar *buf;

	if (unlikely(len < 0))
		failure_return(("len %lld is negative in unzip_literal!\n",len), -1);

	buf = (uchar *)malloc(len);
	if (unlikely(!buf))
		fatal_return(("Failed to malloc literal buffer of size %lld\n", len), -1);

	stream_read = read_stream(control, ss, 1, buf, len);
	if (unlikely(stream_read == -1 )) {
		free(buf);
		fatal_return(("Failed to read_stream in unzip_literal\n"), -1);
	}

	if (unlikely(write_1g(control, buf, (size_t)stream_read) != (ssize_t)stream_read)) {
		free(buf);
		fatal_return(("Failed to write literal buffer of size %lld\n", stream_read), -1);
	}

	if (!HAS_MD5)
		*cksum = CrcUpdate(*cksum, buf, stream_read);
	if (!NO_MD5)
		md5_process_bytes(buf, stream_read, &control->ctx);

	free(buf);
	return stream_read;
}
Exemple #5
0
void
gc_hash_write (gc_hash_handle handle, size_t len, const char *data)
{
  _gc_hash_ctx *ctx = handle;

  switch (ctx->alg)
    {
#ifdef GNULIB_GC_MD2
    case GC_MD2:
      md2_process_bytes (data, len, &ctx->md2Context);
      break;
#endif

#ifdef GNULIB_GC_MD4
    case GC_MD4:
      md4_process_bytes (data, len, &ctx->md4Context);
      break;
#endif

#ifdef GNULIB_GC_MD5
    case GC_MD5:
      md5_process_bytes (data, len, &ctx->md5Context);
      break;
#endif

#ifdef GNULIB_GC_SHA1
    case GC_SHA1:
      sha1_process_bytes (data, len, &ctx->sha1Context);
      break;
#endif

    default:
      break;
    }
}
Exemple #6
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;
}
  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 #8
0
static size_t
init_from_int(int val)
{
    ENTER("");
    md5_process_bytes(&val, sizeof(val), &guid_context);
    LEAVE("");
    return sizeof(int);
}
Exemple #9
0
static size_t
init_from_buff(unsigned char * buf, size_t buflen)
{
    ENTER("");
    md5_process_bytes(buf, buflen, &guid_context);
    LEAVE("");
    return buflen;
}
Exemple #10
0
void http_auth_response_body(http_auth_session *sess, 
			     const char *buffer, size_t buffer_len) 
{
    if (!sess->will_handle ||
	sess->scheme != http_auth_scheme_digest) return;
    DEBUG(DEBUG_HTTPAUTH, "Digesting %d bytes of response body.\n",
	   buffer_len);
    md5_process_bytes(buffer, buffer_len, &sess->response_body);
}
Exemple #11
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 #12
0
static i64 unzip_match(rzip_control *control, void *ss, i64 len, uint32 *cksum, int chunk_bytes)
{
	i64 offset, n, total, cur_pos;
	uchar *buf, *off_buf;

	if (unlikely(len < 0))
		failure_return(("len %lld is negative in unzip_match!\n",len), -1);

	total = 0;
	cur_pos = seekcur_fdout(control);
	if (unlikely(cur_pos == -1))
		fatal_return(("Seek failed on out file in unzip_match.\n"), -1);

	/* Note the offset is in a different format v0.40+ */
	offset = read_vchars(control, ss, 0, chunk_bytes);
	if (unlikely(offset == -1))
		return -1;
	if (unlikely(seekto_fdhist(control, cur_pos - offset) == -1))
		fatal_return(("Seek failed by %d from %d on history file in unzip_match\n",
		      offset, cur_pos), -1);

	buf = (uchar *)malloc(len);
	if (unlikely(!buf))
		fatal_return(("Failed to malloc match buffer of size %lld\n", len), -1);
	off_buf = buf;

	while (len) {
		n = MIN(len, offset);

		if (unlikely(read_fdhist(control, off_buf, (size_t)n) != (ssize_t)n)) {
			free(buf);
			fatal_return(("Failed to read %d bytes in unzip_match\n", n), -1);
		}
		if (unlikely(write_1g(control, off_buf, (size_t)n) != (ssize_t)n)) {
			free(buf);
			fatal_return(("Failed to write %d bytes in unzip_match\n", n), -1);
		}

		if (!HAS_MD5)
			*cksum = CrcUpdate(*cksum, off_buf, n);
		if (!NO_MD5)
			md5_process_bytes(off_buf, n, &control->ctx);

		len -= n;
		off_buf += n;
		total += n;
	}

	free(buf);

	return total;
}
Exemple #13
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 #14
0
static size_t
init_from_file(const char *filename, size_t max_size)
{
    struct stat stats;
    size_t total = 0;
    size_t file_bytes;
    FILE *fp;

    ENTER("filename: %s", filename);

    memset(&stats, 0, sizeof(stats));
    if (g_stat(filename, &stats) != 0)
    {
        LEAVE("unable to read file stats on %s", filename);
        return 0;
    }

    md5_process_bytes(&stats, sizeof(stats), &guid_context);
    total += sizeof(stats);

    if (max_size <= 0)
    {
        LEAVE("no bytes in file %s", filename);
        return total;
    }

    fp = g_fopen (filename, "r");
    if (fp == NULL)
    {
        LEAVE("unable to open file %s", filename);
        return total;
    }

    file_bytes = init_from_stream(fp, max_size);

#ifdef HAVE_SCANF_LLD
    PINFO ("guid_init got %" G_GUINT64_FORMAT " bytes from %s",
	   (guint64) file_bytes,
           filename);
#else
    PINFO ("guid_init got %lu bytes from %s", (unsigned long int) file_bytes,
           filename);
#endif

    total += file_bytes;

    fclose(fp);

    LEAVE("file %s processed successfully", filename);
    return total;
}
Exemple #15
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 #16
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 #17
0
void
gen_md5_update (unsigned const char *buffer, int len, gen_md5_context *ctx)
{
  gen_md5_context_imp *ctx_imp = &ctx->imp;

#ifdef HAVE_BUILTIN_MD5
  md5_process_bytes (buffer, len, ctx_imp);
#endif

#ifdef HAVE_SOLARIS_MD5
  MD5Update (ctx_imp, (unsigned char *)buffer, len);
#endif

#ifdef HAVE_OPENSSL_MD5
  MD5_Update (ctx_imp, buffer, len);
#endif
}
Exemple #18
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 #19
0
/*!
  Update context to reflect the concatenation of another buffer full
  of bytes.
 */
void Md5::update (char const *buf, u_long len)
{
  md5_process_bytes (buf, len, &ctx);
}
Exemple #20
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 #21
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 #22
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 #23
0
// MD5 block update operation. Continues an MD5 message-digest
// operation, processing another message block, and updating the
// context.
void MD5::Update( unsigned char *input, unsigned int inputLen)
{
    md5_process_bytes(input, inputLen, &context);
}
Exemple #24
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 #25
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 #26
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 #27
0
/* Decoder loop for already opened and probably running for some time decoder.
 * next_file will be precached at eof. */
static void decode_loop (const struct decoder *f, void *decoder_data,
		const char *next_file, struct out_buf *out_buf,
		struct sound_params *sound_params, struct md5_data *md5,
		const float already_decoded_sec)
{
	bool eof = false;
	bool stopped = false;
	char buf[PCM_BUF_SIZE];
	int decoded = 0;
	struct sound_params new_sound_params;
	bool sound_params_change = false;
	float decode_time = already_decoded_sec; /* the position of the decoder
						    (in seconds) */

	out_buf_set_free_callback (out_buf, buf_free_callback);

	LOCK (curr_tags_mut);
	curr_tags = tags_new ();
	UNLOCK (curr_tags_mut);

	if (f->get_stream) {
		LOCK (decoder_stream_mut);
		decoder_stream = f->get_stream (decoder_data);
		UNLOCK (decoder_stream_mut);
	}
	else
		logit ("No get_stream() function");

	status_msg ("Playing...");

	while (1) {
		debug ("loop...");

		LOCK (request_cond_mutex);
		if (!eof && !decoded) {
			struct decoder_error err;

			UNLOCK (request_cond_mutex);

			if (decoder_stream && out_buf_get_fill(out_buf)
					< PREBUFFER_THRESHOLD) {
				prebuffering = 1;
				io_prebuffer (decoder_stream,
						options_get_int("Prebuffering")
						* 1024);
				prebuffering = 0;
				status_msg ("Playing...");
			}

			decoded = f->decode (decoder_data, buf, sizeof(buf),
					&new_sound_params);

			if (decoded)
				decode_time += decoded / (float)(sfmt_Bps(
							new_sound_params.fmt) *
						new_sound_params.rate *
						new_sound_params.channels);

			f->get_error (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);
			}

			if (!decoded) {
				eof = true;
				logit ("EOF from decoder");
			}
			else {
				debug ("decoded %d bytes", decoded);
				if (!sound_params_eq(new_sound_params, *sound_params))
					sound_params_change = true;

				bitrate_list_add (&bitrate_list, decode_time,
						f->get_bitrate(decoder_data));
				update_tags (f, decoder_data, decoder_stream);
			}
		}

		/* Wait, if there is no space in the buffer to put the decoded
		 * data or EOF occurred and there is something in the buffer. */
		else if (decoded > out_buf_get_free(out_buf)
					|| (eof && out_buf_get_fill(out_buf))) {
			debug ("waiting...");
			if (eof && !precache.file && next_file
					&& file_type(next_file) == F_SOUND
					&& options_get_int("Precache")
					&& options_get_bool("AutoNext"))
				start_precache (&precache, next_file);
			pthread_cond_wait (&request_cond, &request_cond_mutex);
			UNLOCK (request_cond_mutex);
		}
		else
			UNLOCK (request_cond_mutex);

		/* When clearing request, we must make sure, that another
		 * request will not arrive at the moment, so we check if
		 * the request has changed. */
		if (request == REQ_STOP) {
			logit ("stop");
			stopped = true;
			md5->okay = false;
			out_buf_stop (out_buf);

			LOCK (request_cond_mutex);
			if (request == REQ_STOP)
				request = REQ_NOTHING;
			UNLOCK (request_cond_mutex);

			break;
		}
		else if (request == REQ_SEEK) {
			int decoder_seek;

			logit ("seeking");
			md5->okay = false;
			req_seek = MAX(0, req_seek);
			if ((decoder_seek = f->seek(decoder_data, req_seek))
					== -1)
				logit ("error when seeking");
			else {
				out_buf_stop (out_buf);
				out_buf_reset (out_buf);
				out_buf_time_set (out_buf, decoder_seek);
				bitrate_list_empty (&bitrate_list);
				decode_time = decoder_seek;
				eof = false;
				decoded = 0;
			}

			LOCK (request_cond_mutex);
			if (request == REQ_SEEK)
				request = REQ_NOTHING;
			UNLOCK (request_cond_mutex);

		}
		else if (!eof && decoded <= out_buf_get_free(out_buf)
				&& !sound_params_change) {
			debug ("putting into the buffer %d bytes", decoded);
#if !defined(NDEBUG) && defined(DEBUG)
			if (md5->okay) {
				md5->len += decoded;
				md5_process_bytes (buf, decoded, &md5->ctx);
			}
#endif
			audio_send_buf (buf, decoded);
			decoded = 0;
		}
		else if (!eof && sound_params_change
				&& out_buf_get_fill(out_buf) == 0) {
			logit ("Sound parameters have changed.");
			*sound_params = new_sound_params;
			sound_params_change = false;
			set_info_channels (sound_params->channels);
			set_info_rate (sound_params->rate / 1000);
			out_buf_wait (out_buf);
			if (!audio_open(sound_params)) {
				md5->okay = false;
				break;
			}
		}
		else if (eof && out_buf_get_fill(out_buf) == 0) {
			logit ("played everything");
			break;
		}
	}

	status_msg ("");

	LOCK (decoder_stream_mut);
	decoder_stream = NULL;
	f->close (decoder_data);
	UNLOCK (decoder_stream_mut);

	bitrate_list_destroy (&bitrate_list);

	LOCK (curr_tags_mut);
	if (curr_tags) {
		tags_free (curr_tags);
		curr_tags = NULL;
	}
	UNLOCK (curr_tags_mut);

	out_buf_wait (out_buf);

	if (precache.ok && (stopped || !options_get_bool ("AutoNext"))) {
		precache_wait (&precache);
		precache.f->close (precache.decoder_data);
		precache_reset (&precache);
	}
}
Exemple #28
0
/* This code is based on code in md5.c in GNU textutils. */
static size_t
init_from_stream(FILE *stream, size_t max_size)
{
    char buffer[BLOCKSIZE + 72];
    size_t sum, block_size, total;

    ENTER("");

    if (max_size <= 0)
    {
        LEAVE("max_size is 0 or less, skipping stream");
        return 0;
    }

    total = 0;

    /* Iterate over file contents. */
    while (1)
    {
        /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
         * computation function processes the whole buffer so that with the
         * next round of the loop another block can be read.  */
        size_t n;
        sum = 0;

        if (max_size < BLOCKSIZE)
            block_size = max_size;
        else
            block_size = BLOCKSIZE;

        /* Read block.  Take care for partial reads.  */
        do
        {
            n = fread (buffer + sum, 1, block_size - sum, stream);

            sum += n;
        }
        while (sum < block_size && n != 0);

        max_size -= sum;

        if (n == 0 && ferror (stream))
        {
            LEAVE("error while reading stream");
            return total;
        }

        /* If end of file or max_size is reached, end the loop. */
        if ((n == 0) || (max_size == 0))
            break;

        /* Process buffer with BLOCKSIZE bytes.  Note that
         * BLOCKSIZE % 64 == 0  */
        md5_process_block (buffer, BLOCKSIZE, &guid_context);

        total += sum;
    }

    /* Add the last bytes if necessary.  */
    if (sum > 0)
    {
        md5_process_bytes (buffer, sum, &guid_context);
        total += sum;
    }

    LEAVE("");
    return total;
}
Exemple #29
0
static void
dosum (struct md5_ctx *ctx, const char *file)
{
  FILE *f;
  char buffer[BLOCKSIZE + 72];
  size_t sum;

  f = fopen (file, "rb");
  if (!f)
    {
      fprintf (stderr, "opening %s: %s\n", file, xstrerror (errno));
      exit (1);
    }

  /* Some executable formats have timestamps in the first 16 bytes, yuck.  */
  if (fseek (f, 16, SEEK_SET) != 0)
     {
      fprintf (stderr, "seeking in %s: %s\n", file, xstrerror (errno));
      exit (1);
    }

  /* Iterate over full file contents.  */
  while (1)
    {
      /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
	 computation function processes the whole buffer so that with the
	 next round of the loop another block can be read.  */
      size_t n;
      sum = 0;

      /* Read block.  Take care for partial reads.  */
      do
	{
	  n = fread (buffer + sum, 1, BLOCKSIZE - sum, f);

	  sum += n;
	}
      while (sum < BLOCKSIZE && n != 0);
      if (n == 0 && ferror (f))
        exit (1);

      /* If end of file is reached, end the loop.  */
      if (n == 0)
	break;

      /* Process buffer with BLOCKSIZE bytes.  Note that
			BLOCKSIZE % 64 == 0
       */
      md5_process_block (buffer, BLOCKSIZE, ctx);
    }

  /* Add the last bytes if necessary.  */
  if (sum > 0)
    md5_process_bytes (buffer, sum, ctx);

  if (fclose (f) != 0)
     {
      fprintf (stderr, "reading %s: %s\n", file, xstrerror (errno));
      exit (1);
    }
}
Exemple #30
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;
}